forked from OSchip/llvm-project
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
This commit is contained in:
parent
ac64d2b064
commit
100eb93f89
|
@ -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<SocketAddress> 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<uint16_t> 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.
|
||||
|
|
|
@ -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 <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#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_
|
|
@ -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 = "<group>"; };
|
||||
26022532115F281400A601A2 /* SBFileSpec.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SBFileSpec.cpp; path = source/API/SBFileSpec.cpp; sourceTree = "<group>"; };
|
||||
260A248D15D06C4F009981B0 /* OptionValues.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OptionValues.h; path = include/lldb/Interpreter/OptionValues.h; sourceTree = "<group>"; };
|
||||
260A39A519647A3A004B4130 /* Pipe.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Pipe.h; path = include/lldb/Host/Pipe.h; sourceTree = "<group>"; };
|
||||
260A39A719647A4E004B4130 /* Pipe.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Pipe.cpp; sourceTree = "<group>"; };
|
||||
260A63111860FDB600FECF8E /* Queue.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Queue.h; path = include/lldb/Target/Queue.h; sourceTree = "<group>"; };
|
||||
260A63121860FDBD00FECF8E /* QueueItem.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = QueueItem.h; path = include/lldb/Target/QueueItem.h; sourceTree = "<group>"; };
|
||||
260A63131860FDC700FECF8E /* QueueList.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = QueueList.h; path = include/lldb/Target/QueueList.h; sourceTree = "<group>"; };
|
||||
|
@ -1228,6 +1232,7 @@
|
|||
266DFE9613FD656E00D0C574 /* OperatingSystem.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = OperatingSystem.cpp; path = source/Target/OperatingSystem.cpp; sourceTree = "<group>"; };
|
||||
266DFE9813FD658300D0C574 /* OperatingSystem.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = OperatingSystem.h; path = include/lldb/Target/OperatingSystem.h; sourceTree = "<group>"; };
|
||||
266F5CBB12FC846200DFCE33 /* Config.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Config.h; path = include/lldb/Host/Config.h; sourceTree = "<group>"; };
|
||||
26709E311964A34000B94724 /* LaunchServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = LaunchServices.framework; path = ../../../../../../../System/Library/Frameworks/CoreServices.framework/Frameworks/LaunchServices.framework; sourceTree = "<group>"; };
|
||||
2670F8111862B44A006B332C /* libncurses.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libncurses.dylib; path = /usr/lib/libncurses.dylib; sourceTree = "<absolute>"; };
|
||||
2671A0CD134825F6003A87BB /* ConnectionMachPort.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ConnectionMachPort.h; path = include/lldb/Core/ConnectionMachPort.h; sourceTree = "<group>"; };
|
||||
2671A0CF13482601003A87BB /* ConnectionMachPort.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ConnectionMachPort.cpp; path = source/Core/ConnectionMachPort.cpp; sourceTree = "<group>"; };
|
||||
|
@ -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;
|
||||
|
|
|
@ -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<void*>(this), m_pipe_read,
|
||||
m_pipe_write);
|
||||
static_cast<void*>(this),
|
||||
m_pipe.GetReadFileDescriptor(),
|
||||
m_pipe.GetWriteFileDescriptor());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -180,25 +171,7 @@ ConnectionFileDescriptor::CloseCommandPipe ()
|
|||
log->Printf ("%p ConnectionFileDescriptor::CloseCommandPipe()",
|
||||
static_cast<void*>(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<void*>(this), m_pipe_write, result);
|
||||
static_cast<void*>(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
|
||||
|
|
|
@ -13,6 +13,7 @@ add_lldb_library(lldbHostCommon
|
|||
NativeProcessProtocol.cpp
|
||||
NativeThreadProtocol.cpp
|
||||
OptionParser.cpp
|
||||
Pipe.cpp
|
||||
ProcessRunLock.cpp
|
||||
SocketAddress.cpp
|
||||
SoftwareBreakpoint.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 <unistd.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <io.h>
|
||||
#include <math.h> // TODO: not sure if this is needed for windows, remove if not
|
||||
#include <process.h>// 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
|
||||
}
|
||||
|
|
@ -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<ConnectionFileDescriptor> conn_ap(new ConnectionFileDescriptor(pipe_fds[0], true));
|
||||
std::unique_ptr<ConnectionFileDescriptor> 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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue