forked from OSchip/llvm-project
[lldb] Rename Master/Slave to Primary/Secondary (NFC)
This commit is contained in:
parent
8c6c49f293
commit
64ec505dd4
|
@ -29,36 +29,37 @@ public:
|
|||
|
||||
/// Default constructor
|
||||
///
|
||||
/// Constructs this object with invalid master and slave file descriptors.
|
||||
/// Constructs this object with invalid primary and secondary file
|
||||
/// descriptors.
|
||||
PseudoTerminal();
|
||||
|
||||
/// Destructor
|
||||
///
|
||||
/// The destructor will close the master and slave file descriptors if they
|
||||
/// are valid and ownership has not been released using one of: @li
|
||||
/// PseudoTerminal::ReleaseMasterFileDescriptor() @li
|
||||
/// The destructor will close the primary and secondary file descriptors if
|
||||
/// they are valid and ownership has not been released using one of: @li
|
||||
/// PseudoTerminal::ReleasePrimaryFileDescriptor() @li
|
||||
/// PseudoTerminal::ReleaseSaveFileDescriptor()
|
||||
~PseudoTerminal();
|
||||
|
||||
/// Close the master file descriptor if it is valid.
|
||||
void CloseMasterFileDescriptor();
|
||||
/// Close the primary file descriptor if it is valid.
|
||||
void ClosePrimaryFileDescriptor();
|
||||
|
||||
/// Close the slave file descriptor if it is valid.
|
||||
void CloseSlaveFileDescriptor();
|
||||
/// Close the secondary file descriptor if it is valid.
|
||||
void CloseSecondaryFileDescriptor();
|
||||
|
||||
/// Fork a child process that uses pseudo terminals for its stdio.
|
||||
///
|
||||
/// In the parent process, a call to this function results in a pid being
|
||||
/// returned. If the pid is valid, the master file descriptor can be used
|
||||
/// returned. If the pid is valid, the primary file descriptor can be used
|
||||
/// for read/write access to stdio of the child process.
|
||||
///
|
||||
/// In the child process the stdin/stdout/stderr will already be routed to
|
||||
/// the slave pseudo terminal and the master file descriptor will be closed
|
||||
/// as it is no longer needed by the child process.
|
||||
/// the secondary pseudo terminal and the primary file descriptor will be
|
||||
/// closed as it is no longer needed by the child process.
|
||||
///
|
||||
/// This class will close the file descriptors for the master/slave when the
|
||||
/// destructor is called. The file handles can be released using either: @li
|
||||
/// PseudoTerminal::ReleaseMasterFileDescriptor() @li
|
||||
/// This class will close the file descriptors for the primary/secondary when
|
||||
/// the destructor is called. The file handles can be released using either:
|
||||
/// @li PseudoTerminal::ReleasePrimaryFileDescriptor() @li
|
||||
/// PseudoTerminal::ReleaseSaveFileDescriptor()
|
||||
///
|
||||
/// \param[out] error_str
|
||||
|
@ -71,37 +72,37 @@ public:
|
|||
/// \b Child process: zero.
|
||||
lldb::pid_t Fork(char *error_str, size_t error_len);
|
||||
|
||||
/// The master file descriptor accessor.
|
||||
/// The primary file descriptor accessor.
|
||||
///
|
||||
/// This object retains ownership of the master file descriptor when this
|
||||
/// This object retains ownership of the primary file descriptor when this
|
||||
/// accessor is used. Users can call the member function
|
||||
/// PseudoTerminal::ReleaseMasterFileDescriptor() if this object should
|
||||
/// release ownership of the slave file descriptor.
|
||||
/// PseudoTerminal::ReleasePrimaryFileDescriptor() if this object should
|
||||
/// release ownership of the secondary file descriptor.
|
||||
///
|
||||
/// \return
|
||||
/// The master file descriptor, or PseudoTerminal::invalid_fd
|
||||
/// if the master file descriptor is not currently valid.
|
||||
/// The primary file descriptor, or PseudoTerminal::invalid_fd
|
||||
/// if the primary file descriptor is not currently valid.
|
||||
///
|
||||
/// \see PseudoTerminal::ReleaseMasterFileDescriptor()
|
||||
int GetMasterFileDescriptor() const;
|
||||
/// \see PseudoTerminal::ReleasePrimaryFileDescriptor()
|
||||
int GetPrimaryFileDescriptor() const;
|
||||
|
||||
/// The slave file descriptor accessor.
|
||||
/// The secondary file descriptor accessor.
|
||||
///
|
||||
/// This object retains ownership of the slave file descriptor when this
|
||||
/// This object retains ownership of the secondary file descriptor when this
|
||||
/// accessor is used. Users can call the member function
|
||||
/// PseudoTerminal::ReleaseSlaveFileDescriptor() if this object should
|
||||
/// release ownership of the slave file descriptor.
|
||||
/// PseudoTerminal::ReleaseSecondaryFileDescriptor() if this object should
|
||||
/// release ownership of the secondary file descriptor.
|
||||
///
|
||||
/// \return
|
||||
/// The slave file descriptor, or PseudoTerminal::invalid_fd
|
||||
/// if the slave file descriptor is not currently valid.
|
||||
/// The secondary file descriptor, or PseudoTerminal::invalid_fd
|
||||
/// if the secondary file descriptor is not currently valid.
|
||||
///
|
||||
/// \see PseudoTerminal::ReleaseSlaveFileDescriptor()
|
||||
int GetSlaveFileDescriptor() const;
|
||||
/// \see PseudoTerminal::ReleaseSecondaryFileDescriptor()
|
||||
int GetSecondaryFileDescriptor() const;
|
||||
|
||||
/// Get the name of the slave pseudo terminal.
|
||||
/// Get the name of the secondary pseudo terminal.
|
||||
///
|
||||
/// A master pseudo terminal should already be valid prior to
|
||||
/// A primary pseudo terminal should already be valid prior to
|
||||
/// calling this function.
|
||||
///
|
||||
/// \param[out] error_str
|
||||
|
@ -109,27 +110,27 @@ public:
|
|||
/// occur. This can be NULL if no error status is desired.
|
||||
///
|
||||
/// \return
|
||||
/// The name of the slave pseudo terminal as a NULL terminated
|
||||
/// The name of the secondary pseudo terminal as a NULL terminated
|
||||
/// C. This string that comes from static memory, so a copy of
|
||||
/// the string should be made as subsequent calls can change
|
||||
/// this value. NULL is returned if this object doesn't have
|
||||
/// a valid master pseudo terminal opened or if the call to
|
||||
/// a valid primary pseudo terminal opened or if the call to
|
||||
/// \c ptsname() fails.
|
||||
///
|
||||
/// \see PseudoTerminal::OpenFirstAvailableMaster()
|
||||
const char *GetSlaveName(char *error_str, size_t error_len) const;
|
||||
/// \see PseudoTerminal::OpenFirstAvailablePrimary()
|
||||
const char *GetSecondaryName(char *error_str, size_t error_len) const;
|
||||
|
||||
/// Open the first available pseudo terminal.
|
||||
///
|
||||
/// Opens the first available pseudo terminal with \a oflag as the
|
||||
/// permissions. The opened master file descriptor is stored in this object
|
||||
/// permissions. The opened primary file descriptor is stored in this object
|
||||
/// and can be accessed by calling the
|
||||
/// PseudoTerminal::GetMasterFileDescriptor() accessor. Clients can call the
|
||||
/// PseudoTerminal::ReleaseMasterFileDescriptor() accessor function if they
|
||||
/// wish to use the master file descriptor beyond the lifespan of this
|
||||
/// PseudoTerminal::GetPrimaryFileDescriptor() accessor. Clients can call the
|
||||
/// PseudoTerminal::ReleasePrimaryFileDescriptor() accessor function if they
|
||||
/// wish to use the primary file descriptor beyond the lifespan of this
|
||||
/// object.
|
||||
///
|
||||
/// If this object still has a valid master file descriptor when its
|
||||
/// If this object still has a valid primary file descriptor when its
|
||||
/// destructor is called, it will close it.
|
||||
///
|
||||
/// \param[in] oflag
|
||||
|
@ -141,25 +142,25 @@ public:
|
|||
/// occur. This can be NULL if no error status is desired.
|
||||
///
|
||||
/// \return
|
||||
/// \b true when the master files descriptor is
|
||||
/// \b true when the primary files descriptor is
|
||||
/// successfully opened.
|
||||
/// \b false if anything goes wrong.
|
||||
///
|
||||
/// \see PseudoTerminal::GetMasterFileDescriptor() @see
|
||||
/// PseudoTerminal::ReleaseMasterFileDescriptor()
|
||||
bool OpenFirstAvailableMaster(int oflag, char *error_str, size_t error_len);
|
||||
/// \see PseudoTerminal::GetPrimaryFileDescriptor() @see
|
||||
/// PseudoTerminal::ReleasePrimaryFileDescriptor()
|
||||
bool OpenFirstAvailablePrimary(int oflag, char *error_str, size_t error_len);
|
||||
|
||||
/// Open the slave for the current master pseudo terminal.
|
||||
/// Open the secondary for the current primary pseudo terminal.
|
||||
///
|
||||
/// A master pseudo terminal should already be valid prior to
|
||||
/// calling this function. The opened slave file descriptor is stored in
|
||||
/// A primary pseudo terminal should already be valid prior to
|
||||
/// calling this function. The opened secondary file descriptor is stored in
|
||||
/// this object and can be accessed by calling the
|
||||
/// PseudoTerminal::GetSlaveFileDescriptor() accessor. Clients can call the
|
||||
/// PseudoTerminal::ReleaseSlaveFileDescriptor() accessor function if they
|
||||
/// wish to use the slave file descriptor beyond the lifespan of this
|
||||
/// PseudoTerminal::GetSecondaryFileDescriptor() accessor. Clients can call
|
||||
/// the PseudoTerminal::ReleaseSecondaryFileDescriptor() accessor function if
|
||||
/// they wish to use the secondary file descriptor beyond the lifespan of this
|
||||
/// object.
|
||||
///
|
||||
/// If this object still has a valid slave file descriptor when its
|
||||
/// If this object still has a valid secondary file descriptor when its
|
||||
/// destructor is called, it will close it.
|
||||
///
|
||||
/// \param[in] oflag
|
||||
|
@ -170,43 +171,43 @@ public:
|
|||
/// occur. This can be NULL if no error status is desired.
|
||||
///
|
||||
/// \return
|
||||
/// \b true when the master files descriptor is
|
||||
/// \b true when the primary files descriptor is
|
||||
/// successfully opened.
|
||||
/// \b false if anything goes wrong.
|
||||
///
|
||||
/// \see PseudoTerminal::OpenFirstAvailableMaster() @see
|
||||
/// PseudoTerminal::GetSlaveFileDescriptor() @see
|
||||
/// PseudoTerminal::ReleaseSlaveFileDescriptor()
|
||||
bool OpenSlave(int oflag, char *error_str, size_t error_len);
|
||||
/// \see PseudoTerminal::OpenFirstAvailablePrimary() @see
|
||||
/// PseudoTerminal::GetSecondaryFileDescriptor() @see
|
||||
/// PseudoTerminal::ReleaseSecondaryFileDescriptor()
|
||||
bool OpenSecondary(int oflag, char *error_str, size_t error_len);
|
||||
|
||||
/// Release the master file descriptor.
|
||||
/// Release the primary file descriptor.
|
||||
///
|
||||
/// Releases ownership of the master pseudo terminal file descriptor without
|
||||
/// closing it. The destructor for this class will close the master file
|
||||
/// Releases ownership of the primary pseudo terminal file descriptor without
|
||||
/// closing it. The destructor for this class will close the primary file
|
||||
/// descriptor if the ownership isn't released using this call and the
|
||||
/// master file descriptor has been opened.
|
||||
/// primary file descriptor has been opened.
|
||||
///
|
||||
/// \return
|
||||
/// The master file descriptor, or PseudoTerminal::invalid_fd
|
||||
/// The primary file descriptor, or PseudoTerminal::invalid_fd
|
||||
/// if the mast file descriptor is not currently valid.
|
||||
int ReleaseMasterFileDescriptor();
|
||||
int ReleasePrimaryFileDescriptor();
|
||||
|
||||
/// Release the slave file descriptor.
|
||||
/// Release the secondary file descriptor.
|
||||
///
|
||||
/// Release ownership of the slave pseudo terminal file descriptor without
|
||||
/// closing it. The destructor for this class will close the slave file
|
||||
/// descriptor if the ownership isn't released using this call and the slave
|
||||
/// file descriptor has been opened.
|
||||
/// Release ownership of the secondary pseudo terminal file descriptor without
|
||||
/// closing it. The destructor for this class will close the secondary file
|
||||
/// descriptor if the ownership isn't released using this call and the
|
||||
/// secondary file descriptor has been opened.
|
||||
///
|
||||
/// \return
|
||||
/// The slave file descriptor, or PseudoTerminal::invalid_fd
|
||||
/// if the slave file descriptor is not currently valid.
|
||||
int ReleaseSlaveFileDescriptor();
|
||||
/// The secondary file descriptor, or PseudoTerminal::invalid_fd
|
||||
/// if the secondary file descriptor is not currently valid.
|
||||
int ReleaseSecondaryFileDescriptor();
|
||||
|
||||
protected:
|
||||
// Member variables
|
||||
int m_master_fd; ///< The file descriptor for the master.
|
||||
int m_slave_fd; ///< The file descriptor for the slave.
|
||||
int m_primary_fd; ///< The file descriptor for the primary.
|
||||
int m_secondary_fd; ///< The file descriptor for the secondary.
|
||||
|
||||
private:
|
||||
PseudoTerminal(const PseudoTerminal &) = delete;
|
||||
|
|
|
@ -469,8 +469,6 @@ public:
|
|||
|
||||
const char *GetScriptInterpreterPtyName();
|
||||
|
||||
int GetMasterFileDescriptor();
|
||||
|
||||
virtual llvm::Expected<unsigned>
|
||||
GetMaxPositionalArgumentsForCallable(const llvm::StringRef &callable_name) {
|
||||
return llvm::createStringError(
|
||||
|
|
|
@ -218,26 +218,26 @@ llvm::Error ProcessLaunchInfo::SetUpPtyRedirection() {
|
|||
// do for now.
|
||||
open_flags |= O_CLOEXEC;
|
||||
#endif
|
||||
if (!m_pty->OpenFirstAvailableMaster(open_flags, nullptr, 0)) {
|
||||
if (!m_pty->OpenFirstAvailablePrimary(open_flags, nullptr, 0)) {
|
||||
return llvm::createStringError(llvm::inconvertibleErrorCode(),
|
||||
"PTY::OpenFirstAvailableMaster failed");
|
||||
"PTY::OpenFirstAvailablePrimary failed");
|
||||
}
|
||||
const FileSpec slave_file_spec(m_pty->GetSlaveName(nullptr, 0));
|
||||
const FileSpec secondary_file_spec(m_pty->GetSecondaryName(nullptr, 0));
|
||||
|
||||
// Only use the slave tty if we don't have anything specified for
|
||||
// Only use the secondary tty if we don't have anything specified for
|
||||
// input and don't have an action for stdin
|
||||
if (GetFileActionForFD(STDIN_FILENO) == nullptr)
|
||||
AppendOpenFileAction(STDIN_FILENO, slave_file_spec, true, false);
|
||||
AppendOpenFileAction(STDIN_FILENO, secondary_file_spec, true, false);
|
||||
|
||||
// Only use the slave tty if we don't have anything specified for
|
||||
// Only use the secondary tty if we don't have anything specified for
|
||||
// output and don't have an action for stdout
|
||||
if (GetFileActionForFD(STDOUT_FILENO) == nullptr)
|
||||
AppendOpenFileAction(STDOUT_FILENO, slave_file_spec, false, true);
|
||||
AppendOpenFileAction(STDOUT_FILENO, secondary_file_spec, false, true);
|
||||
|
||||
// Only use the slave tty if we don't have anything specified for
|
||||
// Only use the secondary tty if we don't have anything specified for
|
||||
// error and don't have an action for stderr
|
||||
if (GetFileActionForFD(STDERR_FILENO) == nullptr)
|
||||
AppendOpenFileAction(STDERR_FILENO, slave_file_spec, false, true);
|
||||
AppendOpenFileAction(STDERR_FILENO, secondary_file_spec, false, true);
|
||||
return llvm::Error::success();
|
||||
}
|
||||
|
||||
|
|
|
@ -34,73 +34,73 @@ static void ErrnoToStr(char *error_str, size_t error_len) {
|
|||
|
||||
// PseudoTerminal constructor
|
||||
PseudoTerminal::PseudoTerminal()
|
||||
: m_master_fd(invalid_fd), m_slave_fd(invalid_fd) {}
|
||||
: m_primary_fd(invalid_fd), m_secondary_fd(invalid_fd) {}
|
||||
|
||||
// Destructor
|
||||
//
|
||||
// The destructor will close the master and slave file descriptors if they are
|
||||
// valid and ownership has not been released using the
|
||||
// ReleaseMasterFileDescriptor() or the ReleaseSaveFileDescriptor() member
|
||||
// The destructor will close the primary and secondary file descriptors if they
|
||||
// are valid and ownership has not been released using the
|
||||
// ReleasePrimaryFileDescriptor() or the ReleaseSaveFileDescriptor() member
|
||||
// functions.
|
||||
PseudoTerminal::~PseudoTerminal() {
|
||||
CloseMasterFileDescriptor();
|
||||
CloseSlaveFileDescriptor();
|
||||
ClosePrimaryFileDescriptor();
|
||||
CloseSecondaryFileDescriptor();
|
||||
}
|
||||
|
||||
// Close the master file descriptor if it is valid.
|
||||
void PseudoTerminal::CloseMasterFileDescriptor() {
|
||||
if (m_master_fd >= 0) {
|
||||
::close(m_master_fd);
|
||||
m_master_fd = invalid_fd;
|
||||
// Close the primary file descriptor if it is valid.
|
||||
void PseudoTerminal::ClosePrimaryFileDescriptor() {
|
||||
if (m_primary_fd >= 0) {
|
||||
::close(m_primary_fd);
|
||||
m_primary_fd = invalid_fd;
|
||||
}
|
||||
}
|
||||
|
||||
// Close the slave file descriptor if it is valid.
|
||||
void PseudoTerminal::CloseSlaveFileDescriptor() {
|
||||
if (m_slave_fd >= 0) {
|
||||
::close(m_slave_fd);
|
||||
m_slave_fd = invalid_fd;
|
||||
// Close the secondary file descriptor if it is valid.
|
||||
void PseudoTerminal::CloseSecondaryFileDescriptor() {
|
||||
if (m_secondary_fd >= 0) {
|
||||
::close(m_secondary_fd);
|
||||
m_secondary_fd = invalid_fd;
|
||||
}
|
||||
}
|
||||
|
||||
// Open the first available pseudo terminal with OFLAG as the permissions. The
|
||||
// file descriptor is stored in this object and can be accessed with the
|
||||
// MasterFileDescriptor() accessor. The ownership of the master file descriptor
|
||||
// can be released using the ReleaseMasterFileDescriptor() accessor. If this
|
||||
// object has a valid master files descriptor when its destructor is called, it
|
||||
// will close the master file descriptor, therefore clients must call
|
||||
// ReleaseMasterFileDescriptor() if they wish to use the master file descriptor
|
||||
// after this object is out of scope or destroyed.
|
||||
// PrimaryFileDescriptor() accessor. The ownership of the primary file
|
||||
// descriptor can be released using the ReleasePrimaryFileDescriptor() accessor.
|
||||
// If this object has a valid primary files descriptor when its destructor is
|
||||
// called, it will close the primary file descriptor, therefore clients must
|
||||
// call ReleasePrimaryFileDescriptor() if they wish to use the primary file
|
||||
// descriptor after this object is out of scope or destroyed.
|
||||
//
|
||||
// RETURNS:
|
||||
// True when successful, false indicating an error occurred.
|
||||
bool PseudoTerminal::OpenFirstAvailableMaster(int oflag, char *error_str,
|
||||
size_t error_len) {
|
||||
bool PseudoTerminal::OpenFirstAvailablePrimary(int oflag, char *error_str,
|
||||
size_t error_len) {
|
||||
if (error_str)
|
||||
error_str[0] = '\0';
|
||||
|
||||
#if LLDB_ENABLE_POSIX
|
||||
// Open the master side of a pseudo terminal
|
||||
m_master_fd = ::posix_openpt(oflag);
|
||||
if (m_master_fd < 0) {
|
||||
// Open the primary side of a pseudo terminal
|
||||
m_primary_fd = ::posix_openpt(oflag);
|
||||
if (m_primary_fd < 0) {
|
||||
if (error_str)
|
||||
ErrnoToStr(error_str, error_len);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Grant access to the slave pseudo terminal
|
||||
if (::grantpt(m_master_fd) < 0) {
|
||||
// Grant access to the secondary pseudo terminal
|
||||
if (::grantpt(m_primary_fd) < 0) {
|
||||
if (error_str)
|
||||
ErrnoToStr(error_str, error_len);
|
||||
CloseMasterFileDescriptor();
|
||||
ClosePrimaryFileDescriptor();
|
||||
return false;
|
||||
}
|
||||
|
||||
// Clear the lock flag on the slave pseudo terminal
|
||||
if (::unlockpt(m_master_fd) < 0) {
|
||||
// Clear the lock flag on the secondary pseudo terminal
|
||||
if (::unlockpt(m_primary_fd) < 0) {
|
||||
if (error_str)
|
||||
ErrnoToStr(error_str, error_len);
|
||||
CloseMasterFileDescriptor();
|
||||
ClosePrimaryFileDescriptor();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -112,30 +112,32 @@ bool PseudoTerminal::OpenFirstAvailableMaster(int oflag, char *error_str,
|
|||
#endif
|
||||
}
|
||||
|
||||
// Open the slave pseudo terminal for the current master pseudo terminal. A
|
||||
// master pseudo terminal should already be valid prior to calling this
|
||||
// function (see OpenFirstAvailableMaster()). The file descriptor is stored
|
||||
// Open the secondary pseudo terminal for the current primary pseudo terminal. A
|
||||
// primary pseudo terminal should already be valid prior to calling this
|
||||
// function (see OpenFirstAvailablePrimary()). The file descriptor is stored
|
||||
// this object's member variables and can be accessed via the
|
||||
// GetSlaveFileDescriptor(), or released using the ReleaseSlaveFileDescriptor()
|
||||
// member function.
|
||||
// GetSecondaryFileDescriptor(), or released using the
|
||||
// ReleaseSecondaryFileDescriptor() member function.
|
||||
//
|
||||
// RETURNS:
|
||||
// True when successful, false indicating an error occurred.
|
||||
bool PseudoTerminal::OpenSlave(int oflag, char *error_str, size_t error_len) {
|
||||
bool PseudoTerminal::OpenSecondary(int oflag, char *error_str,
|
||||
size_t error_len) {
|
||||
if (error_str)
|
||||
error_str[0] = '\0';
|
||||
|
||||
CloseSlaveFileDescriptor();
|
||||
CloseSecondaryFileDescriptor();
|
||||
|
||||
// Open the master side of a pseudo terminal
|
||||
const char *slave_name = GetSlaveName(error_str, error_len);
|
||||
// Open the primary side of a pseudo terminal
|
||||
const char *secondary_name = GetSecondaryName(error_str, error_len);
|
||||
|
||||
if (slave_name == nullptr)
|
||||
if (secondary_name == nullptr)
|
||||
return false;
|
||||
|
||||
m_slave_fd = llvm::sys::RetryAfterSignal(-1, ::open, slave_name, oflag);
|
||||
m_secondary_fd =
|
||||
llvm::sys::RetryAfterSignal(-1, ::open, secondary_name, oflag);
|
||||
|
||||
if (m_slave_fd < 0) {
|
||||
if (m_secondary_fd < 0) {
|
||||
if (error_str)
|
||||
ErrnoToStr(error_str, error_len);
|
||||
return false;
|
||||
|
@ -144,46 +146,46 @@ bool PseudoTerminal::OpenSlave(int oflag, char *error_str, size_t error_len) {
|
|||
return true;
|
||||
}
|
||||
|
||||
// Get the name of the slave pseudo terminal. A master pseudo terminal should
|
||||
// already be valid prior to calling this function (see
|
||||
// OpenFirstAvailableMaster()).
|
||||
// Get the name of the secondary pseudo terminal. A primary pseudo terminal
|
||||
// should already be valid prior to calling this function (see
|
||||
// OpenFirstAvailablePrimary()).
|
||||
//
|
||||
// RETURNS:
|
||||
// NULL if no valid master pseudo terminal or if ptsname() fails.
|
||||
// The name of the slave pseudo terminal as a NULL terminated C string
|
||||
// NULL if no valid primary pseudo terminal or if ptsname() fails.
|
||||
// The name of the secondary pseudo terminal as a NULL terminated C string
|
||||
// that comes from static memory, so a copy of the string should be
|
||||
// made as subsequent calls can change this value.
|
||||
const char *PseudoTerminal::GetSlaveName(char *error_str,
|
||||
size_t error_len) const {
|
||||
const char *PseudoTerminal::GetSecondaryName(char *error_str,
|
||||
size_t error_len) const {
|
||||
if (error_str)
|
||||
error_str[0] = '\0';
|
||||
|
||||
if (m_master_fd < 0) {
|
||||
if (m_primary_fd < 0) {
|
||||
if (error_str)
|
||||
::snprintf(error_str, error_len, "%s",
|
||||
"master file descriptor is invalid");
|
||||
"primary file descriptor is invalid");
|
||||
return nullptr;
|
||||
}
|
||||
const char *slave_name = ::ptsname(m_master_fd);
|
||||
const char *secondary_name = ::ptsname(m_primary_fd);
|
||||
|
||||
if (error_str && slave_name == nullptr)
|
||||
if (error_str && secondary_name == nullptr)
|
||||
ErrnoToStr(error_str, error_len);
|
||||
|
||||
return slave_name;
|
||||
return secondary_name;
|
||||
}
|
||||
|
||||
// Fork a child process and have its stdio routed to a pseudo terminal.
|
||||
//
|
||||
// In the parent process when a valid pid is returned, the master file
|
||||
// In the parent process when a valid pid is returned, the primary file
|
||||
// descriptor can be used as a read/write access to stdio of the child process.
|
||||
//
|
||||
// In the child process the stdin/stdout/stderr will already be routed to the
|
||||
// slave pseudo terminal and the master file descriptor will be closed as it is
|
||||
// no longer needed by the child process.
|
||||
// secondary pseudo terminal and the primary file descriptor will be closed as
|
||||
// it is no longer needed by the child process.
|
||||
//
|
||||
// This class will close the file descriptors for the master/slave when the
|
||||
// destructor is called, so be sure to call ReleaseMasterFileDescriptor() or
|
||||
// ReleaseSlaveFileDescriptor() if any file descriptors are going to be used
|
||||
// This class will close the file descriptors for the primary/secondary when the
|
||||
// destructor is called, so be sure to call ReleasePrimaryFileDescriptor() or
|
||||
// ReleaseSecondaryFileDescriptor() if any file descriptors are going to be used
|
||||
// past the lifespan of this object.
|
||||
//
|
||||
// RETURNS:
|
||||
|
@ -196,8 +198,8 @@ lldb::pid_t PseudoTerminal::Fork(char *error_str, size_t error_len) {
|
|||
#if LLDB_ENABLE_POSIX
|
||||
int flags = O_RDWR;
|
||||
flags |= O_CLOEXEC;
|
||||
if (OpenFirstAvailableMaster(flags, error_str, error_len)) {
|
||||
// Successfully opened our master pseudo terminal
|
||||
if (OpenFirstAvailablePrimary(flags, error_str, error_len)) {
|
||||
// Successfully opened our primary pseudo terminal
|
||||
|
||||
pid = ::fork();
|
||||
if (pid < 0) {
|
||||
|
@ -208,32 +210,32 @@ lldb::pid_t PseudoTerminal::Fork(char *error_str, size_t error_len) {
|
|||
// Child Process
|
||||
::setsid();
|
||||
|
||||
if (OpenSlave(O_RDWR, error_str, error_len)) {
|
||||
// Successfully opened slave
|
||||
if (OpenSecondary(O_RDWR, error_str, error_len)) {
|
||||
// Successfully opened secondary
|
||||
|
||||
// Master FD should have O_CLOEXEC set, but let's close it just in
|
||||
// Primary FD should have O_CLOEXEC set, but let's close it just in
|
||||
// case...
|
||||
CloseMasterFileDescriptor();
|
||||
ClosePrimaryFileDescriptor();
|
||||
|
||||
#if defined(TIOCSCTTY)
|
||||
// Acquire the controlling terminal
|
||||
if (::ioctl(m_slave_fd, TIOCSCTTY, (char *)0) < 0) {
|
||||
if (::ioctl(m_secondary_fd, TIOCSCTTY, (char *)0) < 0) {
|
||||
if (error_str)
|
||||
ErrnoToStr(error_str, error_len);
|
||||
}
|
||||
#endif
|
||||
// Duplicate all stdio file descriptors to the slave pseudo terminal
|
||||
if (::dup2(m_slave_fd, STDIN_FILENO) != STDIN_FILENO) {
|
||||
// Duplicate all stdio file descriptors to the secondary pseudo terminal
|
||||
if (::dup2(m_secondary_fd, STDIN_FILENO) != STDIN_FILENO) {
|
||||
if (error_str && !error_str[0])
|
||||
ErrnoToStr(error_str, error_len);
|
||||
}
|
||||
|
||||
if (::dup2(m_slave_fd, STDOUT_FILENO) != STDOUT_FILENO) {
|
||||
if (::dup2(m_secondary_fd, STDOUT_FILENO) != STDOUT_FILENO) {
|
||||
if (error_str && !error_str[0])
|
||||
ErrnoToStr(error_str, error_len);
|
||||
}
|
||||
|
||||
if (::dup2(m_slave_fd, STDERR_FILENO) != STDERR_FILENO) {
|
||||
if (::dup2(m_secondary_fd, STDERR_FILENO) != STDERR_FILENO) {
|
||||
if (error_str && !error_str[0])
|
||||
ErrnoToStr(error_str, error_len);
|
||||
}
|
||||
|
@ -247,41 +249,43 @@ lldb::pid_t PseudoTerminal::Fork(char *error_str, size_t error_len) {
|
|||
return pid;
|
||||
}
|
||||
|
||||
// The master file descriptor accessor. This object retains ownership of the
|
||||
// master file descriptor when this accessor is used. Use
|
||||
// ReleaseMasterFileDescriptor() if you wish this object to release ownership
|
||||
// of the master file descriptor.
|
||||
// The primary file descriptor accessor. This object retains ownership of the
|
||||
// primary file descriptor when this accessor is used. Use
|
||||
// ReleasePrimaryFileDescriptor() if you wish this object to release ownership
|
||||
// of the primary file descriptor.
|
||||
//
|
||||
// Returns the master file descriptor, or -1 if the master file descriptor is
|
||||
// Returns the primary file descriptor, or -1 if the primary file descriptor is
|
||||
// not currently valid.
|
||||
int PseudoTerminal::GetMasterFileDescriptor() const { return m_master_fd; }
|
||||
int PseudoTerminal::GetPrimaryFileDescriptor() const { return m_primary_fd; }
|
||||
|
||||
// The slave file descriptor accessor.
|
||||
// The secondary file descriptor accessor.
|
||||
//
|
||||
// Returns the slave file descriptor, or -1 if the slave file descriptor is not
|
||||
// currently valid.
|
||||
int PseudoTerminal::GetSlaveFileDescriptor() const { return m_slave_fd; }
|
||||
// Returns the secondary file descriptor, or -1 if the secondary file descriptor
|
||||
// is not currently valid.
|
||||
int PseudoTerminal::GetSecondaryFileDescriptor() const {
|
||||
return m_secondary_fd;
|
||||
}
|
||||
|
||||
// Release ownership of the master pseudo terminal file descriptor without
|
||||
// closing it. The destructor for this class will close the master file
|
||||
// descriptor if the ownership isn't released using this call and the master
|
||||
// Release ownership of the primary pseudo terminal file descriptor without
|
||||
// closing it. The destructor for this class will close the primary file
|
||||
// descriptor if the ownership isn't released using this call and the primary
|
||||
// file descriptor has been opened.
|
||||
int PseudoTerminal::ReleaseMasterFileDescriptor() {
|
||||
// Release ownership of the master pseudo terminal file descriptor without
|
||||
int PseudoTerminal::ReleasePrimaryFileDescriptor() {
|
||||
// Release ownership of the primary pseudo terminal file descriptor without
|
||||
// closing it. (the destructor for this class will close it otherwise!)
|
||||
int fd = m_master_fd;
|
||||
m_master_fd = invalid_fd;
|
||||
int fd = m_primary_fd;
|
||||
m_primary_fd = invalid_fd;
|
||||
return fd;
|
||||
}
|
||||
|
||||
// Release ownership of the slave pseudo terminal file descriptor without
|
||||
// closing it. The destructor for this class will close the slave file
|
||||
// descriptor if the ownership isn't released using this call and the slave
|
||||
// Release ownership of the secondary pseudo terminal file descriptor without
|
||||
// closing it. The destructor for this class will close the secondary file
|
||||
// descriptor if the ownership isn't released using this call and the secondary
|
||||
// file descriptor has been opened.
|
||||
int PseudoTerminal::ReleaseSlaveFileDescriptor() {
|
||||
// Release ownership of the slave pseudo terminal file descriptor without
|
||||
int PseudoTerminal::ReleaseSecondaryFileDescriptor() {
|
||||
// Release ownership of the secondary pseudo terminal file descriptor without
|
||||
// closing it (the destructor for this class will close it otherwise!)
|
||||
int fd = m_slave_fd;
|
||||
m_slave_fd = invalid_fd;
|
||||
int fd = m_secondary_fd;
|
||||
m_secondary_fd = invalid_fd;
|
||||
return fd;
|
||||
}
|
||||
|
|
|
@ -362,7 +362,7 @@ PlatformLinux::DebugProcess(ProcessLaunchInfo &launch_info, Debugger &debugger,
|
|||
|
||||
// Hook up process PTY if we have one (which we should for local debugging
|
||||
// with llgs).
|
||||
int pty_fd = launch_info.GetPTY().ReleaseMasterFileDescriptor();
|
||||
int pty_fd = launch_info.GetPTY().ReleasePrimaryFileDescriptor();
|
||||
if (pty_fd != PseudoTerminal::invalid_fd) {
|
||||
process_sp->SetSTDIOFileDescriptor(pty_fd);
|
||||
LLDB_LOG(log, "hooked up STDIO pty to process");
|
||||
|
|
|
@ -194,10 +194,10 @@ lldb::ProcessSP PlatformAppleSimulator::DebugProcess(
|
|||
process_sp->SetShouldDetach(false);
|
||||
|
||||
// If we didn't have any file actions, the pseudo terminal might have
|
||||
// been used where the slave side was given as the file to open for
|
||||
// stdin/out/err after we have already opened the master so we can
|
||||
// been used where the secondary side was given as the file to open for
|
||||
// stdin/out/err after we have already opened the primary so we can
|
||||
// read/write stdin/out/err.
|
||||
int pty_fd = launch_info.GetPTY().ReleaseMasterFileDescriptor();
|
||||
int pty_fd = launch_info.GetPTY().ReleasePrimaryFileDescriptor();
|
||||
if (pty_fd != PseudoTerminal::invalid_fd) {
|
||||
process_sp->SetSTDIOFileDescriptor(pty_fd);
|
||||
}
|
||||
|
|
|
@ -403,22 +403,25 @@ static Status HandleFileAction(ProcessLaunchInfo &launch_info,
|
|||
case FileAction::eFileActionOpen: {
|
||||
FileSpec file_spec = file_action->GetFileSpec();
|
||||
if (file_spec) {
|
||||
const int master_fd = launch_info.GetPTY().GetMasterFileDescriptor();
|
||||
const int master_fd = launch_info.GetPTY().GetPrimaryFileDescriptor();
|
||||
if (master_fd != PseudoTerminal::invalid_fd) {
|
||||
// Check in case our file action open wants to open the slave
|
||||
const char *slave_path = launch_info.GetPTY().GetSlaveName(NULL, 0);
|
||||
if (slave_path) {
|
||||
FileSpec slave_spec(slave_path);
|
||||
if (file_spec == slave_spec) {
|
||||
int slave_fd = launch_info.GetPTY().GetSlaveFileDescriptor();
|
||||
if (slave_fd == PseudoTerminal::invalid_fd)
|
||||
slave_fd = launch_info.GetPTY().OpenSlave(O_RDWR, nullptr, 0);
|
||||
if (slave_fd == PseudoTerminal::invalid_fd) {
|
||||
error.SetErrorStringWithFormat("unable to open slave pty '%s'",
|
||||
slave_path);
|
||||
// Check in case our file action open wants to open the secondary
|
||||
const char *secondary_path =
|
||||
launch_info.GetPTY().GetSecondaryName(NULL, 0);
|
||||
if (secondary_path) {
|
||||
FileSpec secondary_spec(secondary_path);
|
||||
if (file_spec == secondary_spec) {
|
||||
int secondary_fd =
|
||||
launch_info.GetPTY().GetSecondaryFileDescriptor();
|
||||
if (secondary_fd == PseudoTerminal::invalid_fd)
|
||||
secondary_fd =
|
||||
launch_info.GetPTY().OpenSecondary(O_RDWR, nullptr, 0);
|
||||
if (secondary_fd == PseudoTerminal::invalid_fd) {
|
||||
error.SetErrorStringWithFormat(
|
||||
"unable to open secondary pty '%s'", secondary_path);
|
||||
return error; // Failure
|
||||
}
|
||||
[options setValue:[NSNumber numberWithInteger:slave_fd]
|
||||
[options setValue:[NSNumber numberWithInteger:secondary_fd]
|
||||
forKey:key];
|
||||
return error; // Success
|
||||
}
|
||||
|
|
|
@ -331,7 +331,7 @@ PlatformNetBSD::DebugProcess(ProcessLaunchInfo &launch_info, Debugger &debugger,
|
|||
|
||||
// Hook up process PTY if we have one (which we should for local debugging
|
||||
// with llgs).
|
||||
int pty_fd = launch_info.GetPTY().ReleaseMasterFileDescriptor();
|
||||
int pty_fd = launch_info.GetPTY().ReleasePrimaryFileDescriptor();
|
||||
if (pty_fd != PseudoTerminal::invalid_fd) {
|
||||
process_sp->SetSTDIOFileDescriptor(pty_fd);
|
||||
LLDB_LOG(log, "hooked up STDIO pty to process");
|
||||
|
|
|
@ -380,7 +380,8 @@ Status ProcessFreeBSD::DoLaunch(Module *module,
|
|||
FileSpec stdout_file_spec{};
|
||||
FileSpec stderr_file_spec{};
|
||||
|
||||
const FileSpec dbg_pts_file_spec{launch_info.GetPTY().GetSlaveName(NULL, 0)};
|
||||
const FileSpec dbg_pts_file_spec{
|
||||
launch_info.GetPTY().GetSecondaryName(NULL, 0)};
|
||||
|
||||
file_action = launch_info.GetFileActionForFD(STDIN_FILENO);
|
||||
stdin_file_spec =
|
||||
|
|
|
@ -855,7 +855,7 @@ bool ProcessMonitor::Launch(LaunchArgs *args) {
|
|||
// terminal has already dupped the tty descriptors to stdin/out/err. This
|
||||
// closes original fd from which they were copied (and avoids leaking
|
||||
// descriptors to the debugged process.
|
||||
terminal.CloseSlaveFileDescriptor();
|
||||
terminal.CloseSecondaryFileDescriptor();
|
||||
|
||||
// Do not inherit setgid powers.
|
||||
if (setgid(getgid()) != 0)
|
||||
|
@ -939,7 +939,7 @@ bool ProcessMonitor::Launch(LaunchArgs *args) {
|
|||
#endif
|
||||
// Release the master terminal descriptor and pass it off to the
|
||||
// ProcessMonitor instance. Similarly stash the inferior pid.
|
||||
monitor->m_terminal_fd = terminal.ReleaseMasterFileDescriptor();
|
||||
monitor->m_terminal_fd = terminal.ReleasePrimaryFileDescriptor();
|
||||
monitor->m_pid = pid;
|
||||
|
||||
// Set the terminal fd to be in non blocking mode (it simplifies the
|
||||
|
|
|
@ -256,7 +256,7 @@ NativeProcessLinux::Factory::Launch(ProcessLaunchInfo &launch_info,
|
|||
}
|
||||
|
||||
return std::unique_ptr<NativeProcessLinux>(new NativeProcessLinux(
|
||||
pid, launch_info.GetPTY().ReleaseMasterFileDescriptor(), native_delegate,
|
||||
pid, launch_info.GetPTY().ReleasePrimaryFileDescriptor(), native_delegate,
|
||||
Info.GetArchitecture(), mainloop, {pid}));
|
||||
}
|
||||
|
||||
|
|
|
@ -95,7 +95,7 @@ NativeProcessNetBSD::Factory::Launch(ProcessLaunchInfo &launch_info,
|
|||
Info.GetArchitecture().GetArchitectureName());
|
||||
|
||||
std::unique_ptr<NativeProcessNetBSD> process_up(new NativeProcessNetBSD(
|
||||
pid, launch_info.GetPTY().ReleaseMasterFileDescriptor(), native_delegate,
|
||||
pid, launch_info.GetPTY().ReleasePrimaryFileDescriptor(), native_delegate,
|
||||
Info.GetArchitecture(), mainloop));
|
||||
|
||||
// Enable event reporting
|
||||
|
|
|
@ -70,11 +70,11 @@ Status DebuggerThread::DebugLaunch(const ProcessLaunchInfo &launch_info) {
|
|||
Status result;
|
||||
DebugLaunchContext *context = new DebugLaunchContext(this, launch_info);
|
||||
|
||||
llvm::Expected<HostThread> slave_thread = ThreadLauncher::LaunchThread(
|
||||
"lldb.plugin.process-windows.slave[?]", DebuggerThreadLaunchRoutine,
|
||||
context);
|
||||
if (!slave_thread) {
|
||||
result = Status(slave_thread.takeError());
|
||||
llvm::Expected<HostThread> secondary_thread =
|
||||
ThreadLauncher::LaunchThread("lldb.plugin.process-windows.secondary[?]",
|
||||
DebuggerThreadLaunchRoutine, context);
|
||||
if (!secondary_thread) {
|
||||
result = Status(secondary_thread.takeError());
|
||||
LLDB_LOG(log, "couldn't launch debugger thread. {0}", result);
|
||||
}
|
||||
|
||||
|
@ -89,11 +89,11 @@ Status DebuggerThread::DebugAttach(lldb::pid_t pid,
|
|||
Status result;
|
||||
DebugAttachContext *context = new DebugAttachContext(this, pid, attach_info);
|
||||
|
||||
llvm::Expected<HostThread> slave_thread = ThreadLauncher::LaunchThread(
|
||||
"lldb.plugin.process-windows.slave[?]", DebuggerThreadAttachRoutine,
|
||||
context);
|
||||
if (!slave_thread) {
|
||||
result = Status(slave_thread.takeError());
|
||||
llvm::Expected<HostThread> secondary_thread =
|
||||
ThreadLauncher::LaunchThread("lldb.plugin.process-windows.secondary[?]",
|
||||
DebuggerThreadAttachRoutine, context);
|
||||
if (!secondary_thread) {
|
||||
result = Status(secondary_thread.takeError());
|
||||
LLDB_LOG(log, "couldn't attach to process '{0}'. {1}", pid, result);
|
||||
}
|
||||
|
||||
|
@ -411,7 +411,7 @@ DebuggerThread::HandleCreateProcessEvent(const CREATE_PROCESS_DEBUG_INFO &info,
|
|||
|
||||
std::string thread_name;
|
||||
llvm::raw_string_ostream name_stream(thread_name);
|
||||
name_stream << "lldb.plugin.process-windows.slave[" << process_id << "]";
|
||||
name_stream << "lldb.plugin.process-windows.secondary[" << process_id << "]";
|
||||
name_stream.flush();
|
||||
llvm::set_thread_name(thread_name);
|
||||
|
||||
|
|
|
@ -48,7 +48,7 @@ NativeProcessWindows::NativeProcessWindows(ProcessLaunchInfo &launch_info,
|
|||
NativeDelegate &delegate,
|
||||
llvm::Error &E)
|
||||
: NativeProcessProtocol(LLDB_INVALID_PROCESS_ID,
|
||||
launch_info.GetPTY().ReleaseMasterFileDescriptor(),
|
||||
launch_info.GetPTY().ReleasePrimaryFileDescriptor(),
|
||||
delegate),
|
||||
ProcessDebugger(), m_arch(launch_info.GetArchitecture()) {
|
||||
ErrorAsOutParameter EOut(&E);
|
||||
|
|
|
@ -830,22 +830,23 @@ Status ProcessGDBRemote::DoLaunch(lldb_private::Module *exe_module,
|
|||
// since 'O' packets can really slow down debugging if the inferior
|
||||
// does a lot of output.
|
||||
if ((!stdin_file_spec || !stdout_file_spec || !stderr_file_spec) &&
|
||||
pty.OpenFirstAvailableMaster(O_RDWR | O_NOCTTY, nullptr, 0)) {
|
||||
FileSpec slave_name{pty.GetSlaveName(nullptr, 0)};
|
||||
pty.OpenFirstAvailablePrimary(O_RDWR | O_NOCTTY, nullptr, 0)) {
|
||||
FileSpec secondary_name{pty.GetSecondaryName(nullptr, 0)};
|
||||
|
||||
if (!stdin_file_spec)
|
||||
stdin_file_spec = slave_name;
|
||||
stdin_file_spec = secondary_name;
|
||||
|
||||
if (!stdout_file_spec)
|
||||
stdout_file_spec = slave_name;
|
||||
stdout_file_spec = secondary_name;
|
||||
|
||||
if (!stderr_file_spec)
|
||||
stderr_file_spec = slave_name;
|
||||
stderr_file_spec = secondary_name;
|
||||
}
|
||||
LLDB_LOGF(
|
||||
log,
|
||||
"ProcessGDBRemote::%s adjusted STDIO paths for local platform "
|
||||
"(IsHost() is true) using slave: stdin=%s, stdout=%s, stderr=%s",
|
||||
"(IsHost() is true) using secondary: stdin=%s, stdout=%s, "
|
||||
"stderr=%s",
|
||||
__FUNCTION__,
|
||||
stdin_file_spec ? stdin_file_spec.GetCString() : "<null>",
|
||||
stdout_file_spec ? stdout_file_spec.GetCString() : "<null>",
|
||||
|
@ -930,8 +931,8 @@ Status ProcessGDBRemote::DoLaunch(lldb_private::Module *exe_module,
|
|||
SetPrivateState(SetThreadStopInfo(response));
|
||||
|
||||
if (!disable_stdio) {
|
||||
if (pty.GetMasterFileDescriptor() != PseudoTerminal::invalid_fd)
|
||||
SetSTDIOFileDescriptor(pty.ReleaseMasterFileDescriptor());
|
||||
if (pty.GetPrimaryFileDescriptor() != PseudoTerminal::invalid_fd)
|
||||
SetSTDIOFileDescriptor(pty.ReleasePrimaryFileDescriptor());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -489,7 +489,7 @@ ScriptInterpreterPythonImpl::ScriptInterpreterPythonImpl(Debugger &debugger)
|
|||
m_run_one_line_str_global(),
|
||||
m_dictionary_name(m_debugger.GetInstanceName().AsCString()),
|
||||
m_active_io_handler(eIOHandlerNone), m_session_is_active(false),
|
||||
m_pty_slave_is_open(false), m_valid_session(true), m_lock_count(0),
|
||||
m_pty_secondary_is_open(false), m_valid_session(true), m_lock_count(0),
|
||||
m_command_thread_state(nullptr) {
|
||||
InitializePrivate();
|
||||
|
||||
|
|
|
@ -395,7 +395,7 @@ public:
|
|||
std::string m_dictionary_name;
|
||||
ActiveIOHandler m_active_io_handler;
|
||||
bool m_session_is_active;
|
||||
bool m_pty_slave_is_open;
|
||||
bool m_pty_secondary_is_open;
|
||||
bool m_valid_session;
|
||||
uint32_t m_lock_count;
|
||||
PyThreadState *m_command_thread_state;
|
||||
|
|
|
@ -1154,10 +1154,10 @@ Platform::DebugProcess(ProcessLaunchInfo &launch_info, Debugger &debugger,
|
|||
process_sp->SetShouldDetach(false);
|
||||
|
||||
// If we didn't have any file actions, the pseudo terminal might have
|
||||
// been used where the slave side was given as the file to open for
|
||||
// been used where the secondary side was given as the file to open for
|
||||
// stdin/out/err after we have already opened the master so we can
|
||||
// read/write stdin/out/err.
|
||||
int pty_fd = launch_info.GetPTY().ReleaseMasterFileDescriptor();
|
||||
int pty_fd = launch_info.GetPTY().ReleasePrimaryFileDescriptor();
|
||||
if (pty_fd != PseudoTerminal::invalid_fd) {
|
||||
process_sp->SetSTDIOFileDescriptor(pty_fd);
|
||||
}
|
||||
|
|
|
@ -88,21 +88,21 @@ private:
|
|||
|
||||
PseudoTerminal _pty;
|
||||
int _pty_master_fd;
|
||||
int _pty_slave_fd;
|
||||
int _pty_secondary_fd;
|
||||
|
||||
std::unique_ptr<FilePointer> _el_slave_file;
|
||||
std::unique_ptr<FilePointer> _el_secondary_file;
|
||||
};
|
||||
|
||||
EditlineAdapter::EditlineAdapter()
|
||||
: _editline_sp(), _pty(), _pty_master_fd(-1), _pty_slave_fd(-1),
|
||||
_el_slave_file() {
|
||||
: _editline_sp(), _pty(), _pty_master_fd(-1), _pty_secondary_fd(-1),
|
||||
_el_secondary_file() {
|
||||
lldb_private::Status error;
|
||||
|
||||
// Open the first master pty available.
|
||||
char error_string[256];
|
||||
error_string[0] = '\0';
|
||||
if (!_pty.OpenFirstAvailableMaster(O_RDWR, error_string,
|
||||
sizeof(error_string))) {
|
||||
if (!_pty.OpenFirstAvailablePrimary(O_RDWR, error_string,
|
||||
sizeof(error_string))) {
|
||||
fprintf(stderr, "failed to open first available master pty: '%s'\n",
|
||||
error_string);
|
||||
return;
|
||||
|
@ -111,24 +111,24 @@ EditlineAdapter::EditlineAdapter()
|
|||
// Grab the master fd. This is a file descriptor we will:
|
||||
// (1) write to when we want to send input to editline.
|
||||
// (2) read from when we want to see what editline sends back.
|
||||
_pty_master_fd = _pty.GetMasterFileDescriptor();
|
||||
_pty_master_fd = _pty.GetPrimaryFileDescriptor();
|
||||
|
||||
// Open the corresponding slave pty.
|
||||
if (!_pty.OpenSlave(O_RDWR, error_string, sizeof(error_string))) {
|
||||
fprintf(stderr, "failed to open slave pty: '%s'\n", error_string);
|
||||
// Open the corresponding secondary pty.
|
||||
if (!_pty.OpenSecondary(O_RDWR, error_string, sizeof(error_string))) {
|
||||
fprintf(stderr, "failed to open secondary pty: '%s'\n", error_string);
|
||||
return;
|
||||
}
|
||||
_pty_slave_fd = _pty.GetSlaveFileDescriptor();
|
||||
_pty_secondary_fd = _pty.GetSecondaryFileDescriptor();
|
||||
|
||||
_el_slave_file.reset(new FilePointer(fdopen(_pty_slave_fd, "rw")));
|
||||
EXPECT_FALSE(nullptr == *_el_slave_file);
|
||||
if (*_el_slave_file == nullptr)
|
||||
_el_secondary_file.reset(new FilePointer(fdopen(_pty_secondary_fd, "rw")));
|
||||
EXPECT_FALSE(nullptr == *_el_secondary_file);
|
||||
if (*_el_secondary_file == nullptr)
|
||||
return;
|
||||
|
||||
// Create an Editline instance.
|
||||
_editline_sp.reset(new lldb_private::Editline("gtest editor", *_el_slave_file,
|
||||
*_el_slave_file,
|
||||
*_el_slave_file, false));
|
||||
_editline_sp.reset(new lldb_private::Editline(
|
||||
"gtest editor", *_el_secondary_file, *_el_secondary_file,
|
||||
*_el_secondary_file, false));
|
||||
_editline_sp->SetPrompt("> ");
|
||||
|
||||
// Hookup our input complete callback.
|
||||
|
@ -136,8 +136,8 @@ EditlineAdapter::EditlineAdapter()
|
|||
}
|
||||
|
||||
void EditlineAdapter::CloseInput() {
|
||||
if (_el_slave_file != nullptr)
|
||||
_el_slave_file.reset(nullptr);
|
||||
if (_el_secondary_file != nullptr)
|
||||
_el_secondary_file.reset(nullptr);
|
||||
}
|
||||
|
||||
bool EditlineAdapter::SendLine(const std::string &line) {
|
||||
|
|
|
@ -102,17 +102,17 @@ TEST_F(MainLoopTest, TerminatesImmediately) {
|
|||
TEST_F(MainLoopTest, DetectsEOF) {
|
||||
|
||||
PseudoTerminal term;
|
||||
ASSERT_TRUE(term.OpenFirstAvailableMaster(O_RDWR, nullptr, 0));
|
||||
ASSERT_TRUE(term.OpenSlave(O_RDWR | O_NOCTTY, nullptr, 0));
|
||||
ASSERT_TRUE(term.OpenFirstAvailablePrimary(O_RDWR, nullptr, 0));
|
||||
ASSERT_TRUE(term.OpenSecondary(O_RDWR | O_NOCTTY, nullptr, 0));
|
||||
auto conn = std::make_unique<ConnectionFileDescriptor>(
|
||||
term.ReleaseMasterFileDescriptor(), true);
|
||||
term.ReleasePrimaryFileDescriptor(), true);
|
||||
|
||||
Status error;
|
||||
MainLoop loop;
|
||||
auto handle =
|
||||
loop.RegisterReadObject(conn->GetReadObject(), make_callback(), error);
|
||||
ASSERT_TRUE(error.Success());
|
||||
term.CloseSlaveFileDescriptor();
|
||||
term.CloseSecondaryFileDescriptor();
|
||||
|
||||
ASSERT_TRUE(loop.Run().Success());
|
||||
ASSERT_EQ(1u, callback_count);
|
||||
|
|
Loading…
Reference in New Issue