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 || !line) 65 return createStringError(inconvertibleErrorCode(), 66 "Timed out trying to get messages from the " + 67 m_other_endpoint_name); 68 delete future; 69 return json::parse(*line); 70 } 71 72 Error FifoFileIO::SendJSON(const json::Value &json, 73 std::chrono::milliseconds timeout) { 74 bool done = false; 75 std::future<void> *future = 76 new std::future<void>(std::async(std::launch::async, [&]() { 77 std::ofstream writer(m_fifo_file, std::ofstream::out); 78 writer << JSONToString(json) << std::endl; 79 done = true; 80 })); 81 if (future->wait_for(timeout) == std::future_status::timeout || !done) { 82 return createStringError(inconvertibleErrorCode(), 83 "Timed out trying to send messages to the " + 84 m_other_endpoint_name); 85 } 86 delete future; 87 return Error::success(); 88 } 89 90 } // namespace lldb_vscode 91