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:
Greg Clayton 2014-07-02 21:10:39 +00:00
parent ac64d2b064
commit 100eb93f89
8 changed files with 314 additions and 103 deletions

View File

@ -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.

View File

@ -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_

View File

@ -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;

View File

@ -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

View File

@ -13,6 +13,7 @@ add_lldb_library(lldbHostCommon
NativeProcessProtocol.cpp
NativeThreadProtocol.cpp
OptionParser.cpp
Pipe.cpp
ProcessRunLock.cpp
SocketAddress.cpp
SoftwareBreakpoint.cpp

View File

@ -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
}

View File

@ -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

View File

@ -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