1 //===-- FifoFiles.cpp -------------------------------------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "FifoFiles.h" 10 11 #if !defined(_WIN32) 12 #include <sys/stat.h> 13 #include <sys/types.h> 14 #include <unistd.h> 15 #endif 16 17 #include <chrono> 18 #include <fstream> 19 #include <future> 20 #include <thread> 21 22 #include "llvm/Support/FileSystem.h" 23 24 #include "lldb/lldb-defines.h" 25 26 using namespace llvm; 27 28 namespace lldb_vscode { 29 30 FifoFile::FifoFile(StringRef path) : m_path(path) {} 31 32 FifoFile::~FifoFile() { 33 #if !defined(_WIN32) 34 unlink(m_path.c_str()); 35 #endif 36 } 37 38 Expected<std::shared_ptr<FifoFile>> CreateFifoFile(StringRef path) { 39 #if defined(_WIN32) 40 return createStringError(inconvertibleErrorCode(), "Unimplemented"); 41 #else 42 if (int err = mkfifo(path.data(), 0600)) 43 return createStringError(std::error_code(err, std::generic_category()), 44 "Couldn't create fifo file: %s", path.data()); 45 return std::make_shared<FifoFile>(path); 46 #endif 47 } 48 49 FifoFileIO::FifoFileIO(StringRef fifo_file, StringRef other_endpoint_name) 50 : m_fifo_file(fifo_file), m_other_endpoint_name(other_endpoint_name) {} 51 52 Expected<json::Value> FifoFileIO::ReadJSON(std::chrono::milliseconds timeout) { 53 // We use a pointer for this future, because otherwise its normal destructor 54 // would wait for the getline to end, rendering the timeout useless. 55 Optional<std::string> line; 56 std::future<void> *future = 57 new std::future<void>(std::async(std::launch::async, [&]() { 58 std::ifstream reader(m_fifo_file, std::ifstream::in); 59 std::string buffer; 60 std::getline(reader, buffer); 61 if (!buffer.empty()) 62 line = buffer; 63 })); 64 if (future->wait_for(timeout) == std::future_status::timeout || 65 !line.hasValue()) 66 return createStringError(inconvertibleErrorCode(), 67 "Timed out trying to get messages from the " + 68 m_other_endpoint_name); 69 delete future; 70 return json::parse(*line); 71 } 72 73 Error FifoFileIO::SendJSON(const json::Value &json, 74 std::chrono::milliseconds timeout) { 75 bool done = false; 76 std::future<void> *future = 77 new std::future<void>(std::async(std::launch::async, [&]() { 78 std::ofstream writer(m_fifo_file, std::ofstream::out); 79 writer << JSONToString(json) << std::endl; 80 done = true; 81 })); 82 if (future->wait_for(timeout) == std::future_status::timeout || !done) { 83 return createStringError(inconvertibleErrorCode(), 84 "Timed out trying to send messages to the " + 85 m_other_endpoint_name); 86 } 87 delete future; 88 return Error::success(); 89 } 90 91 } // namespace lldb_vscode 92