Index: include/lldb/Host/PipeBase.h =================================================================== --- include/lldb/Host/PipeBase.h +++ include/lldb/Host/PipeBase.h @@ -21,12 +21,15 @@ class PipeBase { public: - virtual ~PipeBase() {} + virtual ~PipeBase(); virtual Error CreateNew(bool child_process_inherit) = 0; virtual Error CreateNew(llvm::StringRef name, bool child_process_inherit) = 0; + virtual Error OpenAsReader(llvm::StringRef name, bool child_process_inherit) = 0; - virtual Error OpenAsWriter(llvm::StringRef name, bool child_process_inherit) = 0; + + Error OpenAsWriter(llvm::StringRef name, bool child_process_inherit); + virtual Error OpenAsWriterWithTimeout(llvm::StringRef name, bool child_process_inherit, const std::chrono::microseconds &timeout) = 0; virtual bool CanRead() const = 0; virtual bool CanWrite() const = 0; @@ -39,9 +42,12 @@ // Close both descriptors virtual void Close() = 0; + // Delete named pipe. + virtual Error Delete(llvm::StringRef name) = 0; + virtual Error Write(const void *buf, size_t size, size_t &bytes_written) = 0; - virtual Error Read(void *buf, size_t size, size_t &bytes_read) = 0; - virtual Error ReadWithTimeout(void *buf, size_t size, const std::chrono::milliseconds &timeout, size_t &bytes_read) = 0; + virtual Error ReadWithTimeout(void *buf, size_t size, const std::chrono::microseconds &timeout, size_t &bytes_read) = 0; + Error Read(void *buf, size_t size, size_t &bytes_read); }; } Index: include/lldb/Host/posix/PipePosix.h =================================================================== --- include/lldb/Host/posix/PipePosix.h +++ include/lldb/Host/posix/PipePosix.h @@ -31,29 +31,46 @@ ~PipePosix() override; - Error CreateNew(bool child_process_inherit) override; - Error CreateNew(llvm::StringRef name, bool child_process_inherit) override; - Error OpenAsReader(llvm::StringRef name, bool child_process_inherit) override; - Error OpenAsWriter(llvm::StringRef name, bool child_process_inherit) override; + Error + CreateNew(bool child_process_inherit) override; + Error + CreateNew(llvm::StringRef name, bool child_process_inherit) override; + Error + OpenAsReader(llvm::StringRef name, bool child_process_inherit) override; + Error + OpenAsWriterWithTimeout(llvm::StringRef name, bool child_process_inherit, const std::chrono::microseconds &timeout) override; - bool CanRead() const override; - bool CanWrite() const override; + bool + CanRead() const override; + bool + CanWrite() const override; - int GetReadFileDescriptor() const override; - int GetWriteFileDescriptor() const override; - int ReleaseReadFileDescriptor() override; - int ReleaseWriteFileDescriptor() override; + int + GetReadFileDescriptor() const override; + int + GetWriteFileDescriptor() const override; + int + ReleaseReadFileDescriptor() override; + int + ReleaseWriteFileDescriptor() override; // Close both descriptors - void Close() override; + void + Close() override; - Error Write(const void *buf, size_t size, size_t &bytes_written) override; - Error Read(void *buf, size_t size, size_t &bytes_read) override; - Error ReadWithTimeout(void *buf, size_t size, const std::chrono::milliseconds &timeout, size_t &bytes_read) override; + Error + Delete(llvm::StringRef name) override; + + Error + Write(const void *buf, size_t size, size_t &bytes_written) override; + Error + ReadWithTimeout(void *buf, size_t size, const std::chrono::microseconds &timeout, size_t &bytes_read) override; private: - void CloseReadFileDescriptor(); - void CloseWriteFileDescriptor(); + void + CloseReadFileDescriptor(); + void + CloseWriteFileDescriptor(); int m_fds[2]; }; Index: include/lldb/Host/windows/PipeWindows.h =================================================================== --- include/lldb/Host/windows/PipeWindows.h +++ include/lldb/Host/windows/PipeWindows.h @@ -32,7 +32,7 @@ Error CreateNew(bool child_process_inherit) override; Error CreateNew(llvm::StringRef name, bool child_process_inherit) override; Error OpenAsReader(llvm::StringRef name, bool child_process_inherit) override; - Error OpenAsWriter(llvm::StringRef name, bool child_process_inherit) override; + Error OpenAsWriterWithTimeout(llvm::StringRef name, bool child_process_inherit, const std::chrono::microseconds &timeout) override; bool CanRead() const override; bool CanWrite() const override; @@ -44,9 +44,10 @@ void Close() override; + Error Delete(llvm::StringRef name) override; + Error Write(const void *buf, size_t size, size_t &bytes_written) override; - Error Read(void *buf, size_t size, size_t &bytes_read) override; - Error ReadWithTimeout(void *buf, size_t size, const std::chrono::milliseconds &timeout, size_t &bytes_read) override; + Error ReadWithTimeout(void *buf, size_t size, const std::chrono::microseconds &timeout, size_t &bytes_read) override; // PipeWindows specific methods. These allow access to the underlying OS handle. HANDLE GetReadNativeHandle(); Index: lldb.xcodeproj/project.pbxproj =================================================================== --- lldb.xcodeproj/project.pbxproj +++ lldb.xcodeproj/project.pbxproj @@ -77,6 +77,7 @@ 23EFE38B193D1AEC00E54E54 /* SBTypeEnumMember.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 23EFE38A193D1AEC00E54E54 /* SBTypeEnumMember.cpp */; }; 23F4034D1926E0F60046DC9B /* NativeRegisterContextRegisterInfo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 23F403481926CC250046DC9B /* NativeRegisterContextRegisterInfo.cpp */; }; 25420ECD1A6490B8009ADBCB /* OptionValueChar.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 25420ECC1A6490B8009ADBCB /* OptionValueChar.cpp */; }; + 25420ED21A649D88009ADBCB /* PipeBase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 25420ED11A649D88009ADBCB /* PipeBase.cpp */; }; 260157C61885F51C00F875CF /* libpanel.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 260157C41885F4FF00F875CF /* libpanel.dylib */; }; 260157C71885F52500F875CF /* libpanel.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 260157C41885F4FF00F875CF /* libpanel.dylib */; }; 260157C81885F53100F875CF /* libpanel.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 260157C41885F4FF00F875CF /* libpanel.dylib */; }; @@ -1031,6 +1032,7 @@ 23F403481926CC250046DC9B /* NativeRegisterContextRegisterInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = NativeRegisterContextRegisterInfo.cpp; path = source/Target/NativeRegisterContextRegisterInfo.cpp; sourceTree = ""; }; 25420ECC1A6490B8009ADBCB /* OptionValueChar.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = OptionValueChar.cpp; path = source/Interpreter/OptionValueChar.cpp; sourceTree = ""; }; 25420ECE1A64911B009ADBCB /* OptionValueChar.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = OptionValueChar.h; path = include/lldb/Interpreter/OptionValueChar.h; sourceTree = ""; }; + 25420ED11A649D88009ADBCB /* PipeBase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PipeBase.cpp; sourceTree = ""; }; 260157C41885F4FF00F875CF /* libpanel.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libpanel.dylib; path = /usr/lib/libpanel.dylib; sourceTree = ""; }; 260223E7115F06D500A601A2 /* SBCommunication.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SBCommunication.h; path = include/lldb/API/SBCommunication.h; sourceTree = ""; }; 260223E8115F06E500A601A2 /* SBCommunication.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SBCommunication.cpp; path = source/API/SBCommunication.cpp; sourceTree = ""; }; @@ -4319,6 +4321,7 @@ 69A01E1A1236C5D400C660B5 /* common */ = { isa = PBXGroup; children = ( + 25420ED11A649D88009ADBCB /* PipeBase.cpp */, 26CFDCA2186163A4000E63E5 /* Editline.cpp */, 260C6EA213011581005E16B0 /* File.cpp */, 26FA43171301048600E71120 /* FileSpec.cpp */, @@ -5261,6 +5264,7 @@ 2689007113353E1A00698AC0 /* Host.cpp in Sources */, 2635879417822FC2004C30BA /* SymbolVendorELF.cpp in Sources */, 2689007213353E1A00698AC0 /* Mutex.cpp in Sources */, + 25420ED21A649D88009ADBCB /* PipeBase.cpp in Sources */, 2689007313353E1A00698AC0 /* Symbols.cpp in Sources */, 26474CBC18D0CB2D0073DEBA /* RegisterContextMach_arm.cpp in Sources */, 2689007413353E1A00698AC0 /* Terminal.cpp in Sources */, Index: source/Host/CMakeLists.txt =================================================================== --- source/Host/CMakeLists.txt +++ source/Host/CMakeLists.txt @@ -21,6 +21,7 @@ common/NativeProcessProtocol.cpp common/NativeThreadProtocol.cpp common/OptionParser.cpp + common/PipeBase.cpp common/ProcessRunLock.cpp common/Socket.cpp common/SocketAddress.cpp Index: source/Host/common/PipeBase.cpp =================================================================== --- /dev/null +++ source/Host/common/PipeBase.cpp @@ -0,0 +1,27 @@ +//===-- source/Host/common/PipeBase.cpp -------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lldb/Host/PipeBase.h" + +using namespace lldb_private; + + +PipeBase::~PipeBase() = default; + +Error +PipeBase::OpenAsWriter(llvm::StringRef name, bool child_process_inherit) +{ + return OpenAsWriterWithTimeout(name, child_process_inherit, std::chrono::microseconds::zero()); +} + +Error +PipeBase::Read(void *buf, size_t size, size_t &bytes_read) +{ + return ReadWithTimeout(buf, size, std::chrono::microseconds::zero(), bytes_read); +} Index: source/Host/posix/PipePosix.cpp =================================================================== --- source/Host/posix/PipePosix.cpp +++ source/Host/posix/PipePosix.cpp @@ -8,11 +8,16 @@ //===----------------------------------------------------------------------===// #include "lldb/Host/posix/PipePosix.h" +#include "lldb/Host/FileSystem.h" + +#include +#include #include #include #include #include +#include using namespace lldb; using namespace lldb_private; @@ -32,6 +37,8 @@ namespace { +constexpr auto OPEN_WRITER_SLEEP_TIMEOUT_MSECS = 100; + #if defined(FD_CLOEXEC) && !PIPE2_SUPPORTED bool SetCloexecFlag(int fd) { @@ -42,6 +49,79 @@ } #endif +std::chrono::time_point +Now() +{ + return std::chrono::steady_clock::now(); +} + +Error +SelectIO(int handle, bool is_read, const std::function &io_handler, const std::chrono::microseconds &timeout) +{ + Error error; + fd_set fds; + bool done = false; + + using namespace std::chrono; + + const auto finish_time = Now() + timeout; + + while (!done) + { + struct timeval tv = {0, 0}; + if (timeout != microseconds::zero()) + { + const auto remaining_dur = duration_cast(finish_time - Now()); + if (remaining_dur.count() <= 0) + { + error.SetErrorString("timeout exceeded"); + break; + } + const auto dur_secs = duration_cast(remaining_dur); + const auto dur_usecs = remaining_dur % seconds(1); + + tv.tv_sec = dur_secs.count(); + tv.tv_usec = dur_usecs.count(); + } + else + tv.tv_sec = 1; + + FD_ZERO(&fds); + FD_SET(handle, &fds); + + const auto retval = ::select(handle + 1, + (is_read) ? &fds : nullptr, + (is_read) ? nullptr : &fds, + nullptr, &tv); + if (retval == -1) + { + if (errno == EINTR) + continue; + error.SetErrorToErrno(); + break; + } + if (retval == 0) + { + error.SetErrorString("timeout exceeded"); + break; + } + if (!FD_ISSET(handle, &fds)) + { + error.SetErrorString("invalid state"); + break; + } + + error = io_handler(done); + if (error.Fail()) + { + if (error.GetError() == EINTR) + continue; + break; + } + } + return error; +} + } PipePosix::PipePosix() @@ -58,13 +138,10 @@ Error PipePosix::CreateNew(bool child_processes_inherit) { - Error error; if (CanRead() || CanWrite()) - { - error.SetError(EINVAL, eErrorTypePOSIX); - return error; - } + return Error(EINVAL, eErrorTypePOSIX); + Error error; #if PIPE2_SUPPORTED if (::pipe2(m_fds, (child_processes_inherit) ? 0 : O_CLOEXEC) == 0) return error; @@ -86,49 +163,85 @@ } #endif + error.SetErrorToErrno(); m_fds[READ] = PipePosix::kInvalidDescriptor; m_fds[WRITE] = PipePosix::kInvalidDescriptor; - error.SetErrorToErrno(); return error; } Error PipePosix::CreateNew(llvm::StringRef name, bool child_process_inherit) { - Error error; if (CanRead() || CanWrite()) - error.SetErrorString("Pipe is already opened"); - else if (name.empty()) - error.SetErrorString("Cannot create named pipe with empty name."); - else - error.SetErrorString("Not implemented"); + return Error("Pipe is already opened"); + + Error error; + if (::mkfifo(name.data(), 0660) != 0) + error.SetErrorToErrno(); + return error; } Error PipePosix::OpenAsReader(llvm::StringRef name, bool child_process_inherit) { - Error error; if (CanRead() || CanWrite()) - error.SetErrorString("Pipe is already opened"); - else if (name.empty()) - error.SetErrorString("Cannot open named pipe with empty name."); + return Error("Pipe is already opened"); + + int flags = O_RDONLY | O_NONBLOCK; + if (!child_process_inherit) + flags |= O_CLOEXEC; + + Error error; + int fd = ::open(name.data(), flags); + if (fd != -1) + m_fds[READ] = fd; else - error.SetErrorString("Not implemented"); + error.SetErrorToErrno(); + return error; } Error -PipePosix::OpenAsWriter(llvm::StringRef name, bool child_process_inherit) +PipePosix::OpenAsWriterWithTimeout(llvm::StringRef name, bool child_process_inherit, const std::chrono::microseconds &timeout) { - Error error; if (CanRead() || CanWrite()) - error.SetErrorString("Pipe is already opened"); - else if (name.empty()) - error.SetErrorString("Cannot create named pipe with empty name."); - else - error.SetErrorString("Not implemented"); - return error; + return Error("Pipe is already opened"); + + int flags = O_WRONLY | O_NONBLOCK; + if (!child_process_inherit) + flags |= O_CLOEXEC; + + using namespace std::chrono; + const auto finish_time = Now() + timeout; + + while (!CanWrite()) + { + if (timeout != microseconds::zero()) + { + const auto dur = duration_cast(finish_time - Now()).count(); + if (dur <= 0) + return Error("timeout exceeded - reader hasn't opened so far"); + } + + errno = 0; + int fd = ::open(name.data(), flags); + if (fd == -1) + { + const auto errno_copy = errno; + // We may get ENXIO if a reader side of the pipe hasn't opened yet. + if (errno_copy != ENXIO) + return Error(errno_copy, eErrorTypePOSIX); + + std::this_thread::sleep_for(milliseconds(OPEN_WRITER_SLEEP_TIMEOUT_MSECS)); + } + else + { + m_fds[WRITE] = fd; + } + } + + return Error(); } int @@ -166,6 +279,12 @@ CloseWriteFileDescriptor(); } +Error +PipePosix::Delete(llvm::StringRef name) +{ + return FileSystem::Unlink(name.data()); +} + bool PipePosix::CanRead() const { @@ -183,8 +302,7 @@ { if (CanRead()) { - int err; - err = close(m_fds[READ]); + close(m_fds[READ]); m_fds[READ] = PipePosix::kInvalidDescriptor; } } @@ -194,59 +312,67 @@ { if (CanWrite()) { - int err; - err = close(m_fds[WRITE]); + close(m_fds[WRITE]); m_fds[WRITE] = PipePosix::kInvalidDescriptor; } } Error -PipePosix::Read(void *buf, size_t num_bytes, size_t &bytes_read) -{ - bytes_read = 0; - Error error; - - if (CanRead()) - { - const int fd = GetReadFileDescriptor(); - int result = read(fd, buf, num_bytes); - if (result >= 0) - bytes_read = result; - else - error.SetErrorToErrno(); - } - else - error.SetError(EINVAL, eErrorTypePOSIX); - - return error; -} - -Error -PipePosix::ReadWithTimeout(void *buf, size_t num_bytes, const std::chrono::milliseconds &duration, size_t &bytes_read) +PipePosix::ReadWithTimeout(void *buf, size_t size, const std::chrono::microseconds &timeout, size_t &bytes_read) { bytes_read = 0; - Error error; - error.SetErrorString("Not implemented"); - return error; + if (!CanRead()) + return Error(EINVAL, eErrorTypePOSIX); + + auto handle = GetReadFileDescriptor(); + return SelectIO(handle, + true, + [=, &bytes_read](bool &done) + { + Error error; + auto result = ::read(handle, + reinterpret_cast(buf) + bytes_read, + size - bytes_read); + if (result != -1) + { + bytes_read += result; + if (bytes_read == size || result == 0) + done = true; + } + else + error.SetErrorToErrno(); + + return error; + }, + timeout); } Error -PipePosix::Write(const void *buf, size_t num_bytes, size_t &bytes_written) +PipePosix::Write(const void *buf, size_t size, size_t &bytes_written) { bytes_written = 0; - Error error; - - if (CanWrite()) - { - const int fd = GetWriteFileDescriptor(); - int result = write(fd, buf, num_bytes); - if (result >= 0) - bytes_written = result; - else - error.SetErrorToErrno(); - } - else - error.SetError(EINVAL, eErrorTypePOSIX); - - return error; + if (!CanWrite()) + return Error(EINVAL, eErrorTypePOSIX); + + auto handle = GetWriteFileDescriptor(); + return SelectIO(handle, + false, + [=, &bytes_written](bool &done) + { + Error error; + auto result = ::write(handle, + reinterpret_cast(buf) + bytes_written, + size - bytes_written); + if (result != -1) + { + bytes_written += result; + if (bytes_written == size) + done = true; + } + else + error.SetErrorToErrno(); + + return error; + }, + std::chrono::microseconds::zero()); } Index: source/Host/windows/PipeWindows.cpp =================================================================== --- source/Host/windows/PipeWindows.cpp +++ source/Host/windows/PipeWindows.cpp @@ -99,7 +99,7 @@ } Error -PipeWindows::OpenAsWriter(llvm::StringRef name, bool child_process_inherit) +PipeWindows::OpenAsWriterWithTimeout(llvm::StringRef name, bool child_process_inherit, const std::chrono::microseconds &timeout) { if (CanRead() || CanWrite()) return Error(ERROR_ALREADY_EXISTS, eErrorTypeWin32); @@ -217,6 +217,12 @@ CloseWriteEndpoint(); } +Error +PipeWindows::Delete(llvm::StringRef name) +{ + return Error(); +} + bool PipeWindows::CanRead() const { @@ -242,13 +248,7 @@ } Error -PipeWindows::Read(void *buf, size_t size, size_t &bytes_read) -{ - return ReadWithTimeout(buf, size, std::chrono::milliseconds::zero(), bytes_read); -} - -Error -PipeWindows::ReadWithTimeout(void *buf, size_t size, const std::chrono::milliseconds &duration, size_t &bytes_read) +PipeWindows::ReadWithTimeout(void *buf, size_t size, const std::chrono::microseconds &duration, size_t &bytes_read) { if (!CanRead()) return Error(ERROR_INVALID_HANDLE, eErrorTypeWin32); @@ -259,7 +259,7 @@ if (!result && GetLastError() != ERROR_IO_PENDING) return Error(::GetLastError(), eErrorTypeWin32); - DWORD timeout = (duration == std::chrono::milliseconds::zero()) ? INFINITE : duration.count(); + DWORD timeout = (duration == std::chrono::microseconds::zero()) ? INFINITE : duration.count() * 1000; DWORD wait_result = ::WaitForSingleObject(m_read_overlapped.hEvent, timeout); if (wait_result != WAIT_OBJECT_0) { Index: source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp =================================================================== --- source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp +++ source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp @@ -22,9 +22,9 @@ #include "lldb/Core/StreamString.h" #include "lldb/Host/ConnectionFileDescriptor.h" #include "lldb/Host/FileSpec.h" -#include "lldb/Host/FileSystem.h" #include "lldb/Host/Host.h" #include "lldb/Host/HostInfo.h" +#include "lldb/Host/Pipe.h" #include "lldb/Host/Socket.h" #include "lldb/Host/ThreadLauncher.h" #include "lldb/Host/TimeValue.h" @@ -763,6 +763,7 @@ char named_pipe_path[PATH_MAX]; named_pipe_path[0] = '\0'; + Pipe port_named_pipe; bool listen = false; if (host_and_port[0]) @@ -788,15 +789,11 @@ if (::mktemp (named_pipe_path)) { -#if defined(_WIN32) - if ( false ) -#else - if (::mkfifo(named_pipe_path, 0600) == 0) -#endif - { - debugserver_args.AppendArgument("--named-pipe"); - debugserver_args.AppendArgument(named_pipe_path); - } + error = port_named_pipe.CreateNew(named_pipe_path, false); + if (error.Fail()) + return error; + debugserver_args.AppendArgument("--named-pipe"); + debugserver_args.AppendArgument(named_pipe_path); } } else @@ -879,20 +876,40 @@ { if (named_pipe_path[0]) { - File name_pipe_file; - error = name_pipe_file.Open(named_pipe_path, File::eOpenOptionRead); + error = port_named_pipe.OpenAsReader(named_pipe_path, false); if (error.Success()) { char port_cstr[256]; port_cstr[0] = '\0'; size_t num_bytes = sizeof(port_cstr); - error = name_pipe_file.Read(port_cstr, num_bytes); - assert (error.Success()); - assert (num_bytes > 0 && port_cstr[num_bytes-1] == '\0'); - out_port = Args::StringToUInt32(port_cstr, 0); - name_pipe_file.Close(); + // Read port from pipe with 10 second timeout. + error = port_named_pipe.ReadWithTimeout(port_cstr, num_bytes, std::chrono::microseconds(10 * 1000000), num_bytes); + if (error.Success()) + { + assert (num_bytes > 0 && port_cstr[num_bytes-1] == '\0'); + out_port = Args::StringToUInt32(port_cstr, 0); + if (log) + log->Printf("GDBRemoteCommunication::%s() debugserver listens %u port", __FUNCTION__, out_port); + } + else + { + if (log) + log->Printf("GDBRemoteCommunication::%s() failed to read a port value from named pipe %s: %s", __FUNCTION__, named_pipe_path, error.AsCString()); + + } + port_named_pipe.Close(); + } + else + { + if (log) + log->Printf("GDBRemoteCommunication::%s() failed to open named pipe %s for reading: %s", __FUNCTION__, named_pipe_path, error.AsCString()); + } + const auto err = port_named_pipe.Delete(named_pipe_path); + if (err.Fail()) + { + if (log) + log->Printf ("GDBRemoteCommunication::%s failed to delete pipe %s: %s", __FUNCTION__, named_pipe_path, err.AsCString()); } - FileSystem::Unlink(named_pipe_path); } else if (listen) { Index: tools/lldb-gdbserver/lldb-gdbserver.cpp =================================================================== --- tools/lldb-gdbserver/lldb-gdbserver.cpp +++ tools/lldb-gdbserver/lldb-gdbserver.cpp @@ -31,6 +31,7 @@ #include "lldb/Core/StreamFile.h" #include "lldb/Host/ConnectionFileDescriptor.h" #include "lldb/Host/HostThread.h" +#include "lldb/Host/Pipe.h" #include "lldb/Host/OptionParser.h" #include "lldb/Host/Socket.h" #include "lldb/Host/ThreadLauncher.h" @@ -309,24 +310,18 @@ Error writePortToPipe (const char *const named_pipe_path, const uint16_t port) { - Error error; - - // FIXME use new generic named pipe support. - int fd = ::open (named_pipe_path, O_WRONLY); - if (fd == -1) - { - error.SetErrorToErrno (); + Pipe port_name_pipe; + // Wait for 10 seconds for pipe to be opened. + auto error = port_name_pipe.OpenAsWriterWithTimeout (named_pipe_path, false, std::chrono::microseconds (10 * 1000000)); + if (error.Fail ()) return error; - } char port_str[64]; - const ssize_t port_str_len = ::snprintf (port_str, sizeof(port_str), "%u", port); - // Write the port number as a C string with the NULL terminator. - if (::write (fd, port_str, port_str_len + 1) == -1) - error.SetErrorToErrno (); + const auto port_str_len = ::snprintf (port_str, sizeof (port_str), "%u", port); - close (fd); - return error; + size_t bytes_written = 0; + // Write the port number as a C string with the NULL terminator. + return port_name_pipe.Write (port_str, port_str_len + 1, bytes_written); } void