From 100eb93f89cc8d9a177e0af7aca8e778a24d62de Mon Sep 17 00:00:00 2001 From: Greg Clayton Date: Wed, 2 Jul 2014 21:10:39 +0000 Subject: [PATCH] Add host layer support for pipes. Windows does support pipes, but they do so in a slightly different way. Added a Host layer which abstracts the use of pipes into a new Pipe class that everyone can use. Windows benefits include: - Being able to interrupt running processes when IO is directly hooked up - being able to interrupt long running python scripts - being able to interrupt anything based on ConnectionFileDescriptor llvm-svn: 212220 --- lldb/include/lldb/Core/ConnectionFileDescriptor.h | 4 +- lldb/include/lldb/Host/Pipe.h | 83 ++++++++++ lldb/lldb.xcodeproj/project.pbxproj | 14 ++ lldb/source/Core/ConnectionFileDescriptor.cpp | 57 ++----- lldb/source/Host/common/CMakeLists.txt | 1 + lldb/source/Host/common/Pipe.cpp | 172 +++++++++++++++++++++ .../source/Interpreter/ScriptInterpreterPython.cpp | 20 +-- lldb/source/Target/Process.cpp | 66 +++----- 8 files changed, 314 insertions(+), 103 deletions(-) create mode 100644 lldb/include/lldb/Host/Pipe.h create mode 100644 lldb/source/Host/common/Pipe.cpp diff --git a/lldb/include/lldb/Core/ConnectionFileDescriptor.h b/lldb/include/lldb/Core/ConnectionFileDescriptor.h index 538a6bf..7e537cc 100644 --- a/lldb/include/lldb/Core/ConnectionFileDescriptor.h +++ b/lldb/include/lldb/Core/ConnectionFileDescriptor.h @@ -24,6 +24,7 @@ // Project includes #include "lldb/Core/Connection.h" #include "lldb/Host/Mutex.h" +#include "lldb/Host/Pipe.h" #include "lldb/Host/Predicate.h" namespace lldb_private { @@ -122,8 +123,7 @@ protected: FDType m_fd_recv_type; std::unique_ptr m_udp_send_sockaddr; uint32_t m_socket_timeout_usec; - int m_pipe_read; // A pipe that we select on the reading end of along with - int m_pipe_write; // m_fd_recv so we can force ourselves out of the select. + Pipe m_pipe; Mutex m_mutex; Predicate m_port_predicate; // Used when binding to port zero to wait for the thread that creates the socket, binds and listens to resolve the port number bool m_should_close_fd; // True if this class should close the file descriptor when it goes away. diff --git a/lldb/include/lldb/Host/Pipe.h b/lldb/include/lldb/Host/Pipe.h new file mode 100644 index 0000000..b36c85c --- /dev/null +++ b/lldb/include/lldb/Host/Pipe.h @@ -0,0 +1,83 @@ +//===-- Pipe.h --------------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_Pipe_h_ +#define liblldb_Pipe_h_ +#if defined(__cplusplus) + +#include +#include +#include + +#include "lldb/lldb-private.h" + +namespace lldb_private { + +//---------------------------------------------------------------------- +/// @class Pipe Pipe.h "lldb/Host/Pipe.h" +/// @brief A class that abtracts unix style pipes. +/// +/// A class that abstracts the LLDB core from host pipe functionality. +//---------------------------------------------------------------------- +class Pipe +{ +public: + static int kInvalidDescriptor; + + Pipe(); + + ~Pipe(); + + bool + Open(); + + bool + IsValid() const; + + bool + ReadDescriptorIsValid() const; + + bool + WriteDescriptorIsValid() const; + + int + GetReadFileDescriptor() const; + + int + GetWriteFileDescriptor() const; + + // Close both descriptors + void + Close(); + + bool + CloseReadFileDescriptor(); + + bool + CloseWriteFileDescriptor(); + + int + ReleaseReadFileDescriptor(); + + int + ReleaseWriteFileDescriptor(); + + size_t + Read (void *buf, size_t size); + + size_t + Write (const void *buf, size_t size); +private: + int m_fds[2]; +}; + +} // namespace lldb_private + +#endif // #if defined(__cplusplus) +#endif // liblldb_Pipe_h_ diff --git a/lldb/lldb.xcodeproj/project.pbxproj b/lldb/lldb.xcodeproj/project.pbxproj index 17409e0..844c3f8 100644 --- a/lldb/lldb.xcodeproj/project.pbxproj +++ b/lldb/lldb.xcodeproj/project.pbxproj @@ -83,6 +83,8 @@ 2606EDDE184E68940034641B /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 260C876910F538E700BB2B04 /* Foundation.framework */; }; 2606EDDF184E68A10034641B /* liblldb-core.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 2689FFCA13353D7A00698AC0 /* liblldb-core.a */; }; 260A248E15D06C50009981B0 /* OptionValues.h in Headers */ = {isa = PBXBuildFile; fileRef = 260A248D15D06C4F009981B0 /* OptionValues.h */; }; + 260A39A619647A3A004B4130 /* Pipe.h in Headers */ = {isa = PBXBuildFile; fileRef = 260A39A519647A3A004B4130 /* Pipe.h */; }; + 260A39A819647A4E004B4130 /* Pipe.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 260A39A719647A4E004B4130 /* Pipe.cpp */; }; 260A63171861008E00FECF8E /* IOHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = 260A63161861008E00FECF8E /* IOHandler.h */; }; 260A63191861009E00FECF8E /* IOHandler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 260A63181861009E00FECF8E /* IOHandler.cpp */; }; 260CC62E15D04377002BF2E0 /* OptionValueArgs.h in Headers */ = {isa = PBXBuildFile; fileRef = 260CC62115D04377002BF2E0 /* OptionValueArgs.h */; }; @@ -949,6 +951,8 @@ 26022531115F27FA00A601A2 /* SBFileSpec.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SBFileSpec.h; path = include/lldb/API/SBFileSpec.h; sourceTree = ""; }; 26022532115F281400A601A2 /* SBFileSpec.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SBFileSpec.cpp; path = source/API/SBFileSpec.cpp; sourceTree = ""; }; 260A248D15D06C4F009981B0 /* OptionValues.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OptionValues.h; path = include/lldb/Interpreter/OptionValues.h; sourceTree = ""; }; + 260A39A519647A3A004B4130 /* Pipe.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Pipe.h; path = include/lldb/Host/Pipe.h; sourceTree = ""; }; + 260A39A719647A4E004B4130 /* Pipe.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Pipe.cpp; sourceTree = ""; }; 260A63111860FDB600FECF8E /* Queue.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Queue.h; path = include/lldb/Target/Queue.h; sourceTree = ""; }; 260A63121860FDBD00FECF8E /* QueueItem.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = QueueItem.h; path = include/lldb/Target/QueueItem.h; sourceTree = ""; }; 260A63131860FDC700FECF8E /* QueueList.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = QueueList.h; path = include/lldb/Target/QueueList.h; sourceTree = ""; }; @@ -1228,6 +1232,7 @@ 266DFE9613FD656E00D0C574 /* OperatingSystem.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = OperatingSystem.cpp; path = source/Target/OperatingSystem.cpp; sourceTree = ""; }; 266DFE9813FD658300D0C574 /* OperatingSystem.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = OperatingSystem.h; path = include/lldb/Target/OperatingSystem.h; sourceTree = ""; }; 266F5CBB12FC846200DFCE33 /* Config.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Config.h; path = include/lldb/Host/Config.h; sourceTree = ""; }; + 26709E311964A34000B94724 /* LaunchServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = LaunchServices.framework; path = ../../../../../../../System/Library/Frameworks/CoreServices.framework/Frameworks/LaunchServices.framework; sourceTree = ""; }; 2670F8111862B44A006B332C /* libncurses.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libncurses.dylib; path = /usr/lib/libncurses.dylib; sourceTree = ""; }; 2671A0CD134825F6003A87BB /* ConnectionMachPort.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ConnectionMachPort.h; path = include/lldb/Core/ConnectionMachPort.h; sourceTree = ""; }; 2671A0CF13482601003A87BB /* ConnectionMachPort.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ConnectionMachPort.cpp; path = source/Core/ConnectionMachPort.cpp; sourceTree = ""; }; @@ -2161,6 +2166,7 @@ 08FB7794FE84155DC02AAC07 /* lldb */ = { isa = PBXGroup; children = ( + 26709E311964A34000B94724 /* LaunchServices.framework */, 26F5C32810F3DF7D009D5894 /* Libraries */, 264E8576159BE51A00E9D7A2 /* Resources */, 08FB7795FE84155DC02AAC07 /* Source */, @@ -3422,6 +3428,7 @@ 232CB611191E00CC00EF39FC /* NativeThreadProtocol.cpp */, 232CB612191E00CC00EF39FC /* NativeThreadProtocol.h */, A36FF33D17D8E98800244D40 /* OptionParser.h */, + 260A39A519647A3A004B4130 /* Pipe.h */, 26BC7DD610F1B7D500F91463 /* Predicate.h */, 26D7E45B13D5E2F9007FD12B /* SocketAddress.h */, 26D7E45C13D5E30A007FD12B /* SocketAddress.cpp */, @@ -3947,6 +3954,7 @@ 69A01E1C1236C5D400C660B5 /* Host.cpp */, 69A01E1E1236C5D400C660B5 /* Mutex.cpp */, A36FF33B17D8E94600244D40 /* OptionParser.cpp */, + 260A39A719647A4E004B4130 /* Pipe.cpp */, 69A01E1F1236C5D400C660B5 /* Symbols.cpp */, 268DA873130095ED00C9483A /* Terminal.cpp */, 69A01E201236C5D400C660B5 /* TimeValue.cpp */, @@ -4190,6 +4198,7 @@ 490A36C2180F0E9300BA31F8 /* PlatformWindows.h in Headers */, 26EFC4CE18CFAF0D00865D87 /* ObjectFileJIT.h in Headers */, 260CC63615D04377002BF2E0 /* OptionValueFormat.h in Headers */, + 260A39A619647A3A004B4130 /* Pipe.h in Headers */, 26D1804516CEE12500EDFB5B /* KQueue.h in Headers */, 260CC63715D04377002BF2E0 /* OptionValueSInt64.h in Headers */, AF061F8C182C980000B6A19C /* HistoryUnwind.h in Headers */, @@ -4845,6 +4854,7 @@ 268900D313353E6F00698AC0 /* ClangExternalASTSourceCallbacks.cpp in Sources */, 268900D413353E6F00698AC0 /* ClangNamespaceDecl.cpp in Sources */, 268900D513353E6F00698AC0 /* CompileUnit.cpp in Sources */, + 260A39A819647A4E004B4130 /* Pipe.cpp in Sources */, 268900D613353E6F00698AC0 /* Declaration.cpp in Sources */, 268900D713353E6F00698AC0 /* DWARFCallFrameInfo.cpp in Sources */, 268900D813353E6F00698AC0 /* Function.cpp in Sources */, @@ -5376,6 +5386,7 @@ FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", "\"$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks\"", + "$(SYSTEM_LIBRARY_DIR)/Frameworks/CoreServices.framework/Frameworks", ); FRAMEWORK_VERSION = A; GCC_INLINES_ARE_PRIVATE_EXTERN = NO; @@ -5440,6 +5451,7 @@ FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", "\"$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks\"", + "$(SYSTEM_LIBRARY_DIR)/Frameworks/CoreServices.framework/Frameworks", ); FRAMEWORK_VERSION = A; GCC_INLINES_ARE_PRIVATE_EXTERN = NO; @@ -5778,6 +5790,7 @@ FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", "\"$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks\"", + "$(SYSTEM_LIBRARY_DIR)/Frameworks/CoreServices.framework/Frameworks", ); FRAMEWORK_VERSION = A; GCC_INLINES_ARE_PRIVATE_EXTERN = NO; @@ -6587,6 +6600,7 @@ FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", "\"$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks\"", + "$(SYSTEM_LIBRARY_DIR)/Frameworks/CoreServices.framework/Frameworks", ); FRAMEWORK_VERSION = A; GCC_INLINES_ARE_PRIVATE_EXTERN = NO; diff --git a/lldb/source/Core/ConnectionFileDescriptor.cpp b/lldb/source/Core/ConnectionFileDescriptor.cpp index 93b2ab7..2f1d16f 100644 --- a/lldb/source/Core/ConnectionFileDescriptor.cpp +++ b/lldb/source/Core/ConnectionFileDescriptor.cpp @@ -97,9 +97,8 @@ ConnectionFileDescriptor::ConnectionFileDescriptor () : m_fd_send_type (eFDTypeFile), m_fd_recv_type (eFDTypeFile), m_udp_send_sockaddr (new SocketAddress()), - m_socket_timeout_usec(0), - m_pipe_read(-1), - m_pipe_write(-1), + m_socket_timeout_usec (0), + m_pipe (), m_mutex (Mutex::eMutexTypeRecursive), m_should_close_fd (false), m_shutting_down (false) @@ -118,8 +117,7 @@ ConnectionFileDescriptor::ConnectionFileDescriptor (int fd, bool owns_fd) : m_fd_recv_type (eFDTypeFile), m_udp_send_sockaddr (new SocketAddress()), m_socket_timeout_usec(0), - m_pipe_read(-1), - m_pipe_write(-1), + m_pipe (), m_mutex (Mutex::eMutexTypeRecursive), m_should_close_fd (owns_fd), m_shutting_down (false) @@ -149,13 +147,7 @@ ConnectionFileDescriptor::OpenCommandPipe () Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION)); // Make the command file descriptor here: - int filedes[2]; -#ifndef LLDB_DISABLE_POSIX - int result = pipe (filedes); -#else - int result = -1; -#endif - if (result != 0) + if (!m_pipe.Open()) { if (log) log->Printf ("%p ConnectionFileDescriptor::OpenCommandPipe () - could not make pipe: %s", @@ -163,12 +155,11 @@ ConnectionFileDescriptor::OpenCommandPipe () } else { - m_pipe_read = filedes[0]; - m_pipe_write = filedes[1]; if (log) log->Printf ("%p ConnectionFileDescriptor::OpenCommandPipe() - success readfd=%d writefd=%d", - static_cast(this), m_pipe_read, - m_pipe_write); + static_cast(this), + m_pipe.GetReadFileDescriptor(), + m_pipe.GetWriteFileDescriptor()); } } @@ -180,25 +171,7 @@ ConnectionFileDescriptor::CloseCommandPipe () log->Printf ("%p ConnectionFileDescriptor::CloseCommandPipe()", static_cast(this)); - if (m_pipe_read != -1) - { -#ifdef _MSC_VER - llvm_unreachable("pipe close unsupported in MSVC"); -#else - close (m_pipe_read); -#endif - m_pipe_read = -1; - } - - if (m_pipe_write != -1) - { -#ifdef _MSC_VER - llvm_unreachable("pipe close unsupported in MSVC"); -#else - close (m_pipe_write); -#endif - m_pipe_write = -1; - } + m_pipe.Close(); } bool @@ -364,9 +337,7 @@ ConnectionFileDescriptor::Connect (const char *s, Error *error_ptr) bool ConnectionFileDescriptor::InterruptRead() { - if (m_pipe_write != -1 ) - return write (m_pipe_write, "i", 1) == 1; - return false; + return m_pipe.Write("i", 1) == 1; } ConnectionStatus @@ -402,13 +373,13 @@ ConnectionFileDescriptor::Disconnect (Error *error_ptr) if (!got_lock) { - if (m_pipe_write != -1 ) + if (m_pipe.WriteDescriptorIsValid()) { int result; - result = write (m_pipe_write, "q", 1); + result = m_pipe.Write("q", 1) == 1; if (log) log->Printf ("%p ConnectionFileDescriptor::Disconnect(): Couldn't get the lock, sent 'q' to %d, result = %d.", - static_cast(this), m_pipe_write, result); + static_cast(this), m_pipe.GetWriteFileDescriptor(), result); } else if (log) log->Printf ("%p ConnectionFileDescriptor::Disconnect(): Couldn't get the lock, but no command pipe is available.", @@ -757,7 +728,7 @@ ConnectionFileDescriptor::BytesAvailable (uint32_t timeout_usec, Error *error_pt // have another thread change these values out from under us // and cause problems in the loop below where like in FS_SET() const int data_fd = m_fd_recv; - const int pipe_fd = m_pipe_read; + const int pipe_fd = m_pipe.GetReadFileDescriptor(); if (data_fd >= 0) { @@ -929,7 +900,7 @@ ConnectionFileDescriptor::BytesAvailable (uint32_t timeout_usec, Error *error_pt // have another thread change these values out from under us // and cause problems in the loop below where like in FS_SET() const int data_fd = m_fd_recv; - const int pipe_fd = m_pipe_read; + const int pipe_fd = m_pipe.GetReadFileDescriptor(); // Make sure the file descriptor can be used with select as it // must be in range diff --git a/lldb/source/Host/common/CMakeLists.txt b/lldb/source/Host/common/CMakeLists.txt index f61af06..0141071 100644 --- a/lldb/source/Host/common/CMakeLists.txt +++ b/lldb/source/Host/common/CMakeLists.txt @@ -13,6 +13,7 @@ add_lldb_library(lldbHostCommon NativeProcessProtocol.cpp NativeThreadProtocol.cpp OptionParser.cpp + Pipe.cpp ProcessRunLock.cpp SocketAddress.cpp SoftwareBreakpoint.cpp diff --git a/lldb/source/Host/common/Pipe.cpp b/lldb/source/Host/common/Pipe.cpp new file mode 100644 index 0000000..d72b916 --- /dev/null +++ b/lldb/source/Host/common/Pipe.cpp @@ -0,0 +1,172 @@ +//===-- Pipe.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/Pipe.h" + +#include + +#ifdef _WIN32 +#include +#include // TODO: not sure if this is needed for windows, remove if not +#include // TODO: not sure if this is needed for windows, remove if not +#endif + +using namespace lldb_private; + +int Pipe::kInvalidDescriptor = -1; + +enum PIPES { READ, WRITE }; // Constants 0 and 1 for READ and WRITE + +Pipe::Pipe() +{ + m_fds[READ] = Pipe::kInvalidDescriptor; + m_fds[WRITE] = Pipe::kInvalidDescriptor; +} + +Pipe::~Pipe() +{ + Close(); +} + +bool +Pipe::Open() +{ + if (IsValid()) + return true; + +#ifdef _WIN32 + if (::_pipe(m_fds, 256, O_BINARY) == 0) + return true +#else + if (::pipe(m_fds) == 0) + return true; +#endif + m_fds[READ] = Pipe::kInvalidDescriptor; + m_fds[WRITE] = Pipe::kInvalidDescriptor; + return false; +} + +int +Pipe::GetReadFileDescriptor() const +{ + return m_fds[READ]; +} + +int +Pipe::GetWriteFileDescriptor() const +{ + return m_fds[WRITE]; +} + +int +Pipe::ReleaseReadFileDescriptor() +{ + const int fd = m_fds[READ]; + m_fds[READ] = Pipe::kInvalidDescriptor; + return fd; +} + +int +Pipe::ReleaseWriteFileDescriptor() +{ + const int fd = m_fds[WRITE]; + m_fds[WRITE] = Pipe::kInvalidDescriptor; + return fd; +} + +void +Pipe::Close() +{ + CloseReadFileDescriptor(); + CloseWriteFileDescriptor(); +} + +bool +Pipe::ReadDescriptorIsValid() const +{ + return m_fds[READ] != Pipe::kInvalidDescriptor; +} + +bool +Pipe::WriteDescriptorIsValid() const +{ + return m_fds[WRITE] != Pipe::kInvalidDescriptor; +} + +bool +Pipe::IsValid() const +{ + return ReadDescriptorIsValid() && WriteDescriptorIsValid(); +} + +bool +Pipe::CloseReadFileDescriptor() +{ + if (ReadDescriptorIsValid()) + { + int err; +#ifdef _WIN32 + err = _close(m_fds[READ]); +#else + err = close(m_fds[READ]); +#endif + m_fds[READ] = Pipe::kInvalidDescriptor; + return err == 0; + } + return true; +} + +bool +Pipe::CloseWriteFileDescriptor() +{ + if (WriteDescriptorIsValid()) + { + int err; +#ifdef _WIN32 + err = _close(m_fds[WRITE]); +#else + err = close(m_fds[WRITE]); +#endif + m_fds[WRITE] = Pipe::kInvalidDescriptor; + return err == 0; + } + return true; +} + + +size_t +Pipe::Read (void *buf, size_t num_bytes) +{ + if (ReadDescriptorIsValid()) + { + const int fd = GetReadFileDescriptor(); +#ifdef _WIN32 + return _read (fd, (char *)buf, num_bytes); +#else + return read (fd, buf, num_bytes); +#endif + } + return 0; // Return 0 since errno won't be set if we didn't call read +} + +size_t +Pipe::Write (const void *buf, size_t num_bytes) +{ + if (WriteDescriptorIsValid()) + { + const int fd = GetWriteFileDescriptor(); +#ifdef _WIN32 + return _write (fd, (char *)buf, num_bytes); +#else + return write (fd, buf, num_bytes); +#endif + } + return 0; // Return 0 since errno won't be set if we didn't call write +} + diff --git a/lldb/source/Interpreter/ScriptInterpreterPython.cpp b/lldb/source/Interpreter/ScriptInterpreterPython.cpp index ef0d71b..8120c4b 100644 --- a/lldb/source/Interpreter/ScriptInterpreterPython.cpp +++ b/lldb/source/Interpreter/ScriptInterpreterPython.cpp @@ -32,6 +32,7 @@ #include "lldb/Core/Debugger.h" #include "lldb/Core/Timer.h" #include "lldb/Host/Host.h" +#include "lldb/Host/Pipe.h" #include "lldb/Interpreter/CommandInterpreter.h" #include "lldb/Interpreter/CommandReturnObject.h" #include "lldb/Interpreter/PythonDataObjects.h" @@ -580,8 +581,7 @@ ScriptInterpreterPython::ExecuteOneLine (const char *command, CommandReturnObjec StreamFileSP output_file_sp; StreamFileSP error_file_sp; Communication output_comm ("lldb.ScriptInterpreterPython.ExecuteOneLine.comm"); - int pipe_fds[2] = { -1, -1 }; - + bool join_read_thread = false; if (options.GetEnableIO()) { if (result) @@ -589,21 +589,17 @@ ScriptInterpreterPython::ExecuteOneLine (const char *command, CommandReturnObjec input_file_sp = debugger.GetInputFile(); // Set output to a temporary file so we can forward the results on to the result object -#ifdef _MSC_VER - // pipe is not supported on windows so default to a fail condition - int err = 1; -#else - int err = pipe(pipe_fds); -#endif - if (err == 0) + Pipe pipe; + if (pipe.Open()) { - std::unique_ptr conn_ap(new ConnectionFileDescriptor(pipe_fds[0], true)); + std::unique_ptr conn_ap(new ConnectionFileDescriptor(pipe.ReleaseReadFileDescriptor(), true)); if (conn_ap->IsConnected()) { output_comm.SetConnection(conn_ap.release()); output_comm.SetReadThreadBytesReceivedCallback(ReadThreadBytesReceived, &result->GetOutputStream()); output_comm.StartReadThread(); - FILE *outfile_handle = fdopen (pipe_fds[1], "w"); + join_read_thread = true; + FILE *outfile_handle = fdopen (pipe.ReleaseWriteFileDescriptor(), "w"); output_file_sp.reset(new StreamFile(outfile_handle, true)); error_file_sp = output_file_sp; if (outfile_handle) @@ -672,7 +668,7 @@ ScriptInterpreterPython::ExecuteOneLine (const char *command, CommandReturnObjec if (out_file != err_file) ::fflush (err_file); - if (pipe_fds[0] != -1) + if (join_read_thread) { // Close the write end of the pipe since we are done with our // one line script. This should cause the read thread that diff --git a/lldb/source/Target/Process.cpp b/lldb/source/Target/Process.cpp index 6f5125a..d6f1eaa 100644 --- a/lldb/source/Target/Process.cpp +++ b/lldb/source/Target/Process.cpp @@ -27,6 +27,7 @@ #include "lldb/Expression/ClangUserExpression.h" #include "lldb/Interpreter/CommandInterpreter.h" #include "lldb/Host/Host.h" +#include "lldb/Host/Pipe.h" #include "lldb/Host/Terminal.h" #include "lldb/Target/ABI.h" #include "lldb/Target/DynamicLoader.h" @@ -4442,8 +4443,7 @@ public: m_process (process), m_read_file (), m_write_file (write_fd, false), - m_pipe_read(), - m_pipe_write() + m_pipe () { m_read_file.SetDescriptor(GetInputFD(), false); } @@ -4457,30 +4457,15 @@ public: bool OpenPipes () { - if (m_pipe_read.IsValid() && m_pipe_write.IsValid()) + if (m_pipe.IsValid()) return true; - - int fds[2]; -#ifdef _WIN32 - // pipe is not supported on windows so default to a fail condition - int err = 1; -#else - int err = pipe(fds); -#endif - if (err == 0) - { - m_pipe_read.SetDescriptor(fds[0], true); - m_pipe_write.SetDescriptor(fds[1], true); - return true; - } - return false; + return m_pipe.Open(); } void ClosePipes() { - m_pipe_read.Close(); - m_pipe_write.Close(); + m_pipe.Close(); } // Each IOHandler gets to run until it is done. It should read data @@ -4495,7 +4480,7 @@ public: if (OpenPipes()) { const int read_fd = m_read_file.GetDescriptor(); - const int pipe_read_fd = m_pipe_read.GetDescriptor(); + const int pipe_read_fd = m_pipe.GetReadFileDescriptor(); TerminalState terminal_state; terminal_state.Save (read_fd, false); Terminal terminal(read_fd); @@ -4536,17 +4521,18 @@ public: if (FD_ISSET (pipe_read_fd, &read_fdset)) { // Consume the interrupt byte - n = 1; - m_pipe_read.Read (&ch, n); - switch (ch) + if (m_pipe.Read (&ch, 1) == 1) { - case 'q': - SetIsDone(true); - break; - case 'i': - if (StateIsRunningState(m_process->GetState())) - m_process->Halt(); - break; + switch (ch) + { + case 'q': + SetIsDone(true); + break; + case 'i': + if (StateIsRunningState(m_process->GetState())) + m_process->Halt(); + break; + } } } } @@ -4582,30 +4568,20 @@ public: virtual void Cancel () { - size_t n = 1; char ch = 'q'; // Send 'q' for quit - m_pipe_write.Write (&ch, n); + m_pipe.Write (&ch, 1); } virtual bool Interrupt () { -#ifdef _MSC_VER - // Windows doesn't support pipes, so we will send an async interrupt - // event to stop the process - if (StateIsRunningState(m_process->GetState())) - m_process->SendAsyncInterrupt(); -#else // Do only things that are safe to do in an interrupt context (like in // a SIGINT handler), like write 1 byte to a file descriptor. This will // interrupt the IOHandlerProcessSTDIO::Run() and we can look at the byte // that was written to the pipe and then call m_process->Halt() from a // much safer location in code. - size_t n = 1; char ch = 'i'; // Send 'i' for interrupt - m_pipe_write.Write (&ch, n); -#endif - return true; + return m_pipe.Write (&ch, 1) == 1; } virtual void @@ -4618,9 +4594,7 @@ protected: Process *m_process; File m_read_file; // Read from this file (usually actual STDIN for LLDB File m_write_file; // Write to this file (usually the master pty for getting io to debuggee) - File m_pipe_read; - File m_pipe_write; - + Pipe m_pipe; }; void -- 2.7.4