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