[Lldb-commits] [lldb] r295368 - Finish breaking the dependency from Utility.
Zachary Turner via lldb-commits
lldb-commits at lists.llvm.org
Thu Feb 16 11:38:22 PST 2017
Modified: lldb/trunk/source/Host/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Host/CMakeLists.txt?rev=295368&r1=295367&r2=295368&view=diff
==============================================================================
--- lldb/trunk/source/Host/CMakeLists.txt (original)
+++ lldb/trunk/source/Host/CMakeLists.txt Thu Feb 16 13:38:21 2017
@@ -27,6 +27,7 @@ add_host_subdirectory(common
common/OptionParser.cpp
common/PipeBase.cpp
common/ProcessRunLock.cpp
+ common/PseudoTerminal.cpp
common/Socket.cpp
common/SocketAddress.cpp
common/SoftwareBreakpoint.cpp
Added: lldb/trunk/source/Host/common/PseudoTerminal.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Host/common/PseudoTerminal.cpp?rev=295368&view=auto
==============================================================================
--- lldb/trunk/source/Host/common/PseudoTerminal.cpp (added)
+++ lldb/trunk/source/Host/common/PseudoTerminal.cpp Thu Feb 16 13:38:21 2017
@@ -0,0 +1,310 @@
+//===-- PseudoTerminal.cpp --------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Host/PseudoTerminal.h"
+#include "lldb/Host/Config.h"
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#if defined(TIOCSCTTY)
+#include <sys/ioctl.h>
+#endif
+
+#include "lldb/Host/PosixApi.h"
+
+#if defined(__ANDROID__)
+int posix_openpt(int flags);
+#endif
+
+using namespace lldb_utility;
+
+//----------------------------------------------------------------------
+// PseudoTerminal constructor
+//----------------------------------------------------------------------
+PseudoTerminal::PseudoTerminal()
+ : m_master_fd(invalid_fd), m_slave_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 functions.
+//----------------------------------------------------------------------
+PseudoTerminal::~PseudoTerminal() {
+ CloseMasterFileDescriptor();
+ CloseSlaveFileDescriptor();
+}
+
+//----------------------------------------------------------------------
+// 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 slave file descriptor if it is valid.
+//----------------------------------------------------------------------
+void PseudoTerminal::CloseSlaveFileDescriptor() {
+ if (m_slave_fd >= 0) {
+ ::close(m_slave_fd);
+ m_slave_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.
+//
+// RETURNS:
+// True when successful, false indicating an error occurred.
+//----------------------------------------------------------------------
+bool PseudoTerminal::OpenFirstAvailableMaster(int oflag, char *error_str,
+ size_t error_len) {
+ if (error_str)
+ error_str[0] = '\0';
+
+#if !defined(LLDB_DISABLE_POSIX)
+ // Open the master side of a pseudo terminal
+ m_master_fd = ::posix_openpt(oflag);
+ if (m_master_fd < 0) {
+ if (error_str)
+ ::strerror_r(errno, error_str, error_len);
+ return false;
+ }
+
+ // Grant access to the slave pseudo terminal
+ if (::grantpt(m_master_fd) < 0) {
+ if (error_str)
+ ::strerror_r(errno, error_str, error_len);
+ CloseMasterFileDescriptor();
+ return false;
+ }
+
+ // Clear the lock flag on the slave pseudo terminal
+ if (::unlockpt(m_master_fd) < 0) {
+ if (error_str)
+ ::strerror_r(errno, error_str, error_len);
+ CloseMasterFileDescriptor();
+ return false;
+ }
+
+ return true;
+#else
+ if (error_str)
+ ::snprintf(error_str, error_len, "%s", "pseudo terminal not supported");
+ return false;
+#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 this object's member variables and can
+// be accessed via the GetSlaveFileDescriptor(), or released using the
+// ReleaseSlaveFileDescriptor() member function.
+//
+// RETURNS:
+// True when successful, false indicating an error occurred.
+//----------------------------------------------------------------------
+bool PseudoTerminal::OpenSlave(int oflag, char *error_str, size_t error_len) {
+ if (error_str)
+ error_str[0] = '\0';
+
+ CloseSlaveFileDescriptor();
+
+ // Open the master side of a pseudo terminal
+ const char *slave_name = GetSlaveName(error_str, error_len);
+
+ if (slave_name == nullptr)
+ return false;
+
+ m_slave_fd = ::open(slave_name, oflag);
+
+ if (m_slave_fd < 0) {
+ if (error_str)
+ ::strerror_r(errno, error_str, error_len);
+ return false;
+ }
+
+ 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()).
+//
+// 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
+// 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 {
+ if (error_str)
+ error_str[0] = '\0';
+
+ if (m_master_fd < 0) {
+ if (error_str)
+ ::snprintf(error_str, error_len, "%s",
+ "master file descriptor is invalid");
+ return nullptr;
+ }
+ const char *slave_name = ::ptsname(m_master_fd);
+
+ if (error_str && slave_name == nullptr)
+ ::strerror_r(errno, error_str, error_len);
+
+ return slave_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
+// 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.
+//
+// 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 past the lifespan of this
+// object.
+//
+// RETURNS:
+// in the parent process: the pid of the child, or -1 if fork fails
+// in the child process: zero
+//----------------------------------------------------------------------
+lldb::pid_t PseudoTerminal::Fork(char *error_str, size_t error_len) {
+ if (error_str)
+ error_str[0] = '\0';
+ pid_t pid = LLDB_INVALID_PROCESS_ID;
+#if !defined(LLDB_DISABLE_POSIX)
+ int flags = O_RDWR;
+ flags |= O_CLOEXEC;
+ if (OpenFirstAvailableMaster(flags, error_str, error_len)) {
+ // Successfully opened our master pseudo terminal
+
+ pid = ::fork();
+ if (pid < 0) {
+ // Fork failed
+ if (error_str)
+ ::strerror_r(errno, error_str, error_len);
+ } else if (pid == 0) {
+ // Child Process
+ ::setsid();
+
+ if (OpenSlave(O_RDWR, error_str, error_len)) {
+ // Successfully opened slave
+
+ // Master FD should have O_CLOEXEC set, but let's close it just in
+ // case...
+ CloseMasterFileDescriptor();
+
+#if defined(TIOCSCTTY)
+ // Acquire the controlling terminal
+ if (::ioctl(m_slave_fd, TIOCSCTTY, (char *)0) < 0) {
+ if (error_str)
+ ::strerror_r(errno, error_str, error_len);
+ }
+#endif
+ // Duplicate all stdio file descriptors to the slave pseudo terminal
+ if (::dup2(m_slave_fd, STDIN_FILENO) != STDIN_FILENO) {
+ if (error_str && !error_str[0])
+ ::strerror_r(errno, error_str, error_len);
+ }
+
+ if (::dup2(m_slave_fd, STDOUT_FILENO) != STDOUT_FILENO) {
+ if (error_str && !error_str[0])
+ ::strerror_r(errno, error_str, error_len);
+ }
+
+ if (::dup2(m_slave_fd, STDERR_FILENO) != STDERR_FILENO) {
+ if (error_str && !error_str[0])
+ ::strerror_r(errno, error_str, error_len);
+ }
+ }
+ } else {
+ // Parent Process
+ // Do nothing and let the pid get returned!
+ }
+ }
+#endif
+ 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.
+//
+// Returns the master file descriptor, or -1 if the master file
+// descriptor is not currently valid.
+//----------------------------------------------------------------------
+int PseudoTerminal::GetMasterFileDescriptor() const { return m_master_fd; }
+
+//----------------------------------------------------------------------
+// The slave 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; }
+
+//----------------------------------------------------------------------
+// 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 file descriptor has been opened.
+//----------------------------------------------------------------------
+int PseudoTerminal::ReleaseMasterFileDescriptor() {
+ // Release ownership of the master 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;
+ 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 file descriptor has been opened.
+//----------------------------------------------------------------------
+int PseudoTerminal::ReleaseSlaveFileDescriptor() {
+ // Release ownership of the slave 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;
+ return fd;
+}
Modified: lldb/trunk/source/Interpreter/ScriptInterpreter.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Interpreter/ScriptInterpreter.cpp?rev=295368&r1=295367&r2=295368&view=diff
==============================================================================
--- lldb/trunk/source/Interpreter/ScriptInterpreter.cpp (original)
+++ lldb/trunk/source/Interpreter/ScriptInterpreter.cpp Thu Feb 16 13:38:21 2017
@@ -14,9 +14,9 @@
#include <string>
#include "lldb/Core/StringList.h"
+#include "lldb/Host/PseudoTerminal.h"
#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Utility/Error.h"
-#include "lldb/Utility/PseudoTerminal.h"
#include "lldb/Utility/Stream.h"
using namespace lldb;
Modified: lldb/trunk/source/Plugins/Platform/MacOSX/PlatformAppleSimulator.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Platform/MacOSX/PlatformAppleSimulator.cpp?rev=295368&r1=295367&r2=295368&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Platform/MacOSX/PlatformAppleSimulator.cpp (original)
+++ lldb/trunk/source/Plugins/Platform/MacOSX/PlatformAppleSimulator.cpp Thu Feb 16 13:38:21 2017
@@ -19,10 +19,10 @@
#include <thread>
// Other libraries and framework includes
// Project includes
+#include "lldb/Host/PseudoTerminal.h"
#include "lldb/Target/Process.h"
#include "lldb/Utility/Error.h"
#include "lldb/Utility/LLDBAssert.h"
-#include "lldb/Utility/PseudoTerminal.h"
#include "lldb/Utility/StreamString.h"
#include "llvm/Support/Threading.h"
Modified: lldb/trunk/source/Plugins/Platform/MacOSX/PlatformiOSSimulatorCoreSimulatorSupport.mm
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Platform/MacOSX/PlatformiOSSimulatorCoreSimulatorSupport.mm?rev=295368&r1=295367&r2=295368&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Platform/MacOSX/PlatformiOSSimulatorCoreSimulatorSupport.mm (original)
+++ lldb/trunk/source/Plugins/Platform/MacOSX/PlatformiOSSimulatorCoreSimulatorSupport.mm Thu Feb 16 13:38:21 2017
@@ -16,8 +16,8 @@
#include <CoreFoundation/CoreFoundation.h>
#include <Foundation/Foundation.h>
// Project includes
+#include "lldb/Host/PseudoTerminal.h"
#include "lldb/Target/FileAction.h"
-#include "lldb/Utility/PseudoTerminal.h"
#include "llvm/ADT/StringRef.h"
Modified: lldb/trunk/source/Plugins/Process/Darwin/DarwinProcessLauncher.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Darwin/DarwinProcessLauncher.cpp?rev=295368&r1=295367&r2=295368&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Darwin/DarwinProcessLauncher.cpp (original)
+++ lldb/trunk/source/Plugins/Process/Darwin/DarwinProcessLauncher.cpp Thu Feb 16 13:38:21 2017
@@ -31,9 +31,9 @@
#include "lldb/lldb-enumerations.h"
#include "lldb/Core/Log.h"
+#include "lldb/Host/PseudoTerminal.h"
#include "lldb/Target/ProcessLaunchInfo.h"
#include "lldb/Utility/Error.h"
-#include "lldb/Utility/PseudoTerminal.h"
#include "lldb/Utility/StreamString.h"
#include "CFBundle.h"
Modified: lldb/trunk/source/Plugins/Process/Darwin/NativeProcessDarwin.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Darwin/NativeProcessDarwin.cpp?rev=295368&r1=295367&r2=295368&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Darwin/NativeProcessDarwin.cpp (original)
+++ lldb/trunk/source/Plugins/Process/Darwin/NativeProcessDarwin.cpp Thu Feb 16 13:38:21 2017
@@ -21,8 +21,8 @@
// LLDB includes
#include "lldb/Core/Log.h"
#include "lldb/Core/State.h"
+#include "lldb/Host/PseudoTerminal.h"
#include "lldb/Target/ProcessLaunchInfo.h"
-#include "lldb/Utility/PseudoTerminal.h"
#include "lldb/Utility/StreamString.h"
#include "CFBundle.h"
Modified: lldb/trunk/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp?rev=295368&r1=295367&r2=295368&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp (original)
+++ lldb/trunk/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp Thu Feb 16 13:38:21 2017
@@ -24,12 +24,12 @@
#include "lldb/Core/RegisterValue.h"
#include "lldb/Core/Scalar.h"
#include "lldb/Host/Host.h"
+#include "lldb/Host/PseudoTerminal.h"
#include "lldb/Host/ThreadLauncher.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/Thread.h"
#include "lldb/Target/UnixSignals.h"
#include "lldb/Utility/Error.h"
-#include "lldb/Utility/PseudoTerminal.h"
#include "FreeBSDThread.h"
#include "Plugins/Process/POSIX/CrashReason.h"
Modified: lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.cpp?rev=295368&r1=295367&r2=295368&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.cpp (original)
+++ lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.cpp Thu Feb 16 13:38:21 2017
@@ -29,6 +29,7 @@
#include "lldb/Core/State.h"
#include "lldb/Host/Host.h"
#include "lldb/Host/HostProcess.h"
+#include "lldb/Host/PseudoTerminal.h"
#include "lldb/Host/ThreadLauncher.h"
#include "lldb/Host/common/NativeBreakpoint.h"
#include "lldb/Host/common/NativeRegisterContext.h"
@@ -41,7 +42,6 @@
#include "lldb/Target/Target.h"
#include "lldb/Utility/Error.h"
#include "lldb/Utility/LLDBAssert.h"
-#include "lldb/Utility/PseudoTerminal.h"
#include "lldb/Utility/StringExtractor.h"
#include "NativeThreadLinux.h"
Modified: lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp?rev=295368&r1=295367&r2=295368&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp (original)
+++ lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp Thu Feb 16 13:38:21 2017
@@ -42,6 +42,7 @@
#include "lldb/Host/FileSpec.h"
#include "lldb/Host/FileSystem.h"
#include "lldb/Host/HostThread.h"
+#include "lldb/Host/PseudoTerminal.h"
#include "lldb/Host/StringConvert.h"
#include "lldb/Host/Symbols.h"
#include "lldb/Host/ThreadLauncher.h"
@@ -64,7 +65,6 @@
#include "lldb/Target/TargetList.h"
#include "lldb/Target/ThreadPlanCallFunction.h"
#include "lldb/Utility/CleanUp.h"
-#include "lldb/Utility/PseudoTerminal.h"
#include "lldb/Utility/StreamString.h"
// Project includes
Modified: lldb/trunk/source/Utility/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Utility/CMakeLists.txt?rev=295368&r1=295367&r2=295368&view=diff
==============================================================================
--- lldb/trunk/source/Utility/CMakeLists.txt (original)
+++ lldb/trunk/source/Utility/CMakeLists.txt Thu Feb 16 13:38:21 2017
@@ -4,7 +4,6 @@ add_lldb_library(lldbUtility
JSON.cpp
LLDBAssert.cpp
NameMatches.cpp
- PseudoTerminal.cpp
Range.cpp
RegularExpression.cpp
SelectHelper.cpp
@@ -16,9 +15,10 @@ add_lldb_library(lldbUtility
StringLexer.cpp
TaskPool.cpp
UriParser.cpp
+ VASprintf.cpp
LINK_LIBS
- lldbHost
+ # lldbUtility cannot have any dependencies
LINK_COMPONENTS
Support
Modified: lldb/trunk/source/Utility/Error.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Utility/Error.cpp?rev=295368&r1=295367&r2=295368&view=diff
==============================================================================
--- lldb/trunk/source/Utility/Error.cpp (original)
+++ lldb/trunk/source/Utility/Error.cpp Thu Feb 16 13:38:21 2017
@@ -20,8 +20,8 @@
#include "llvm/ADT/SmallVector.h"
// Project includes
-#include "lldb/Host/PosixApi.h"
#include "lldb/Utility/Error.h"
+#include "lldb/Utility/VASPrintf.h"
using namespace lldb;
using namespace lldb_private;
@@ -233,25 +233,9 @@ int Error::SetErrorStringWithVarArg(cons
if (Success())
SetErrorToGenericError();
- // Try and fit our error into a 1024 byte buffer first...
- llvm::SmallVector<char, 1024> buf;
- buf.resize(1024);
- // Copy in case our first call to vsnprintf doesn't fit into our
- // allocated buffer above
- va_list copy_args;
- va_copy(copy_args, args);
- unsigned length = ::vsnprintf(buf.data(), buf.size(), format, args);
- if (length >= buf.size()) {
- // The error formatted string didn't fit into our buffer, resize it
- // to the exact needed size, and retry
- buf.resize(length + 1);
- length = ::vsnprintf(buf.data(), buf.size(), format, copy_args);
- va_end(copy_args);
- assert(length < buf.size());
- }
- m_string.assign(buf.data(), length);
- va_end(args);
- return length;
+ llvm::SmallString<1024> buf;
+ VASprintf(buf, format, args);
+ return buf.size();
} else {
m_string.clear();
}
Removed: lldb/trunk/source/Utility/PseudoTerminal.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Utility/PseudoTerminal.cpp?rev=295367&view=auto
==============================================================================
--- lldb/trunk/source/Utility/PseudoTerminal.cpp (original)
+++ lldb/trunk/source/Utility/PseudoTerminal.cpp (removed)
@@ -1,311 +0,0 @@
-//===-- PseudoTerminal.cpp --------------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "lldb/Utility/PseudoTerminal.h"
-#include "lldb/Host/Config.h"
-
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#if defined(TIOCSCTTY)
-#include <sys/ioctl.h>
-#endif
-
-#include "lldb/Host/PosixApi.h"
-
-#if defined(__ANDROID__)
-int posix_openpt(int flags);
-#endif
-
-using namespace lldb_utility;
-
-//----------------------------------------------------------------------
-// PseudoTerminal constructor
-//----------------------------------------------------------------------
-PseudoTerminal::PseudoTerminal()
- : m_master_fd(invalid_fd), m_slave_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 functions.
-//----------------------------------------------------------------------
-PseudoTerminal::~PseudoTerminal() {
- CloseMasterFileDescriptor();
- CloseSlaveFileDescriptor();
-}
-
-//----------------------------------------------------------------------
-// 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 slave file descriptor if it is valid.
-//----------------------------------------------------------------------
-void PseudoTerminal::CloseSlaveFileDescriptor() {
- if (m_slave_fd >= 0) {
- ::close(m_slave_fd);
- m_slave_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.
-//
-// RETURNS:
-// True when successful, false indicating an error occurred.
-//----------------------------------------------------------------------
-bool PseudoTerminal::OpenFirstAvailableMaster(int oflag, char *error_str,
- size_t error_len) {
- if (error_str)
- error_str[0] = '\0';
-
-#if !defined(LLDB_DISABLE_POSIX)
- // Open the master side of a pseudo terminal
- m_master_fd = ::posix_openpt(oflag);
- if (m_master_fd < 0) {
- if (error_str)
- ::strerror_r(errno, error_str, error_len);
- return false;
- }
-
- // Grant access to the slave pseudo terminal
- if (::grantpt(m_master_fd) < 0) {
- if (error_str)
- ::strerror_r(errno, error_str, error_len);
- CloseMasterFileDescriptor();
- return false;
- }
-
- // Clear the lock flag on the slave pseudo terminal
- if (::unlockpt(m_master_fd) < 0) {
- if (error_str)
- ::strerror_r(errno, error_str, error_len);
- CloseMasterFileDescriptor();
- return false;
- }
-
- return true;
-#else
- if (error_str)
- ::snprintf(error_str, error_len, "%s",
- "pseudo terminal not supported");
- return false;
-#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 this object's member variables and can
-// be accessed via the GetSlaveFileDescriptor(), or released using the
-// ReleaseSlaveFileDescriptor() member function.
-//
-// RETURNS:
-// True when successful, false indicating an error occurred.
-//----------------------------------------------------------------------
-bool PseudoTerminal::OpenSlave(int oflag, char *error_str, size_t error_len) {
- if (error_str)
- error_str[0] = '\0';
-
- CloseSlaveFileDescriptor();
-
- // Open the master side of a pseudo terminal
- const char *slave_name = GetSlaveName(error_str, error_len);
-
- if (slave_name == nullptr)
- return false;
-
- m_slave_fd = ::open(slave_name, oflag);
-
- if (m_slave_fd < 0) {
- if (error_str)
- ::strerror_r(errno, error_str, error_len);
- return false;
- }
-
- 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()).
-//
-// 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
-// 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 {
- if (error_str)
- error_str[0] = '\0';
-
- if (m_master_fd < 0) {
- if (error_str)
- ::snprintf(error_str, error_len, "%s",
- "master file descriptor is invalid");
- return nullptr;
- }
- const char *slave_name = ::ptsname(m_master_fd);
-
- if (error_str && slave_name == nullptr)
- ::strerror_r(errno, error_str, error_len);
-
- return slave_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
-// 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.
-//
-// 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 past the lifespan of this
-// object.
-//
-// RETURNS:
-// in the parent process: the pid of the child, or -1 if fork fails
-// in the child process: zero
-//----------------------------------------------------------------------
-lldb::pid_t PseudoTerminal::Fork(char *error_str, size_t error_len) {
- if (error_str)
- error_str[0] = '\0';
- pid_t pid = LLDB_INVALID_PROCESS_ID;
-#if !defined(LLDB_DISABLE_POSIX)
- int flags = O_RDWR;
- flags |= O_CLOEXEC;
- if (OpenFirstAvailableMaster(flags, error_str, error_len)) {
- // Successfully opened our master pseudo terminal
-
- pid = ::fork();
- if (pid < 0) {
- // Fork failed
- if (error_str)
- ::strerror_r(errno, error_str, error_len);
- } else if (pid == 0) {
- // Child Process
- ::setsid();
-
- if (OpenSlave(O_RDWR, error_str, error_len)) {
- // Successfully opened slave
-
- // Master FD should have O_CLOEXEC set, but let's close it just in
- // case...
- CloseMasterFileDescriptor();
-
-#if defined(TIOCSCTTY)
- // Acquire the controlling terminal
- if (::ioctl(m_slave_fd, TIOCSCTTY, (char *)0) < 0) {
- if (error_str)
- ::strerror_r(errno, error_str, error_len);
- }
-#endif
- // Duplicate all stdio file descriptors to the slave pseudo terminal
- if (::dup2(m_slave_fd, STDIN_FILENO) != STDIN_FILENO) {
- if (error_str && !error_str[0])
- ::strerror_r(errno, error_str, error_len);
- }
-
- if (::dup2(m_slave_fd, STDOUT_FILENO) != STDOUT_FILENO) {
- if (error_str && !error_str[0])
- ::strerror_r(errno, error_str, error_len);
- }
-
- if (::dup2(m_slave_fd, STDERR_FILENO) != STDERR_FILENO) {
- if (error_str && !error_str[0])
- ::strerror_r(errno, error_str, error_len);
- }
- }
- } else {
- // Parent Process
- // Do nothing and let the pid get returned!
- }
- }
-#endif
- 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.
-//
-// Returns the master file descriptor, or -1 if the master file
-// descriptor is not currently valid.
-//----------------------------------------------------------------------
-int PseudoTerminal::GetMasterFileDescriptor() const { return m_master_fd; }
-
-//----------------------------------------------------------------------
-// The slave 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; }
-
-//----------------------------------------------------------------------
-// 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 file descriptor has been opened.
-//----------------------------------------------------------------------
-int PseudoTerminal::ReleaseMasterFileDescriptor() {
- // Release ownership of the master 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;
- 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 file descriptor has been opened.
-//----------------------------------------------------------------------
-int PseudoTerminal::ReleaseSlaveFileDescriptor() {
- // Release ownership of the slave 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;
- return fd;
-}
Modified: lldb/trunk/source/Utility/Stream.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Utility/Stream.cpp?rev=295368&r1=295367&r2=295368&view=diff
==============================================================================
--- lldb/trunk/source/Utility/Stream.cpp (original)
+++ lldb/trunk/source/Utility/Stream.cpp Thu Feb 16 13:38:21 2017
@@ -8,8 +8,9 @@
//===----------------------------------------------------------------------===//
#include "lldb/Utility/Stream.h"
-#include "lldb/Host/PosixApi.h"
+
#include "lldb/Utility/Endian.h"
+#include "lldb/Utility/VASPrintf.h"
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
@@ -162,36 +163,14 @@ size_t Stream::Printf(const char *format
// Print some formatted output to the stream.
//------------------------------------------------------------------
size_t Stream::PrintfVarArg(const char *format, va_list args) {
- char str[1024];
- va_list args_copy;
-
- va_copy(args_copy, args);
+ llvm::SmallString<1024> buf;
+ VASprintf(buf, format, args);
- size_t bytes_written = 0;
- // Try and format our string into a fixed buffer first and see if it fits
- size_t length = ::vsnprintf(str, sizeof(str), format, args);
- if (length < sizeof(str)) {
- // Include the NULL termination byte for binary output
- if (m_flags.Test(eBinary))
- length += 1;
- // The formatted string fit into our stack based buffer, so we can just
- // append that to our packet
- bytes_written = Write(str, length);
- } else {
- // Our stack buffer wasn't big enough to contain the entire formatted
- // string, so lets let vasprintf create the string for us!
- char *str_ptr = NULL;
- length = ::vasprintf(&str_ptr, format, args_copy);
- if (str_ptr) {
- // Include the NULL termination byte for binary output
- if (m_flags.Test(eBinary))
- length += 1;
- bytes_written = Write(str_ptr, length);
- ::free(str_ptr);
- }
- }
- va_end(args_copy);
- return bytes_written;
+ // Include the NULL termination byte for binary output
+ size_t length = buf.size();
+ if (m_flags.Test(eBinary))
+ ++length;
+ return Write(buf.c_str(), length);
}
//------------------------------------------------------------------
@@ -358,34 +337,18 @@ lldb::ByteOrder Stream::GetByteOrder() c
size_t Stream::PrintfAsRawHex8(const char *format, ...) {
va_list args;
- va_list args_copy;
va_start(args, format);
- va_copy(args_copy, args); // Copy this so we
- char str[1024];
- size_t bytes_written = 0;
- // Try and format our string into a fixed buffer first and see if it fits
- size_t length = ::vsnprintf(str, sizeof(str), format, args);
- if (length < sizeof(str)) {
- // The formatted string fit into our stack based buffer, so we can just
- // append that to our packet
- for (size_t i = 0; i < length; ++i)
- bytes_written += _PutHex8(str[i], false);
- } else {
- // Our stack buffer wasn't big enough to contain the entire formatted
- // string, so lets let vasprintf create the string for us!
- char *str_ptr = NULL;
- length = ::vasprintf(&str_ptr, format, args_copy);
- if (str_ptr) {
- for (size_t i = 0; i < length; ++i)
- bytes_written += _PutHex8(str_ptr[i], false);
- ::free(str_ptr);
- }
- }
+ llvm::SmallString<1024> buf;
+ VASprintf(buf, format, args);
+
+ size_t length = 0;
+ for (char C : buf)
+ length += _PutHex8(C, false);
+
va_end(args);
- va_end(args_copy);
- return bytes_written;
+ return length;
}
size_t Stream::PutNHex8(size_t n, uint8_t uvalue) {
Added: lldb/trunk/source/Utility/VASprintf.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Utility/VASprintf.cpp?rev=295368&view=auto
==============================================================================
--- lldb/trunk/source/Utility/VASprintf.cpp (added)
+++ lldb/trunk/source/Utility/VASprintf.cpp Thu Feb 16 13:38:21 2017
@@ -0,0 +1,52 @@
+//===-- VASPrintf.cpp -------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Utility/VASprintf.h"
+
+#include "llvm/ADT/SmallString.h"
+
+using namespace lldb_private;
+
+bool lldb_private::VASprintf(llvm::SmallVectorImpl<char> &buf, const char *fmt,
+ va_list args) {
+ llvm::SmallString<16> error("<Encoding error>");
+ bool result = true;
+
+ // Copy in case our first call to vsnprintf doesn't fit into our buffer
+ va_list copy_args;
+ va_copy(copy_args, args);
+
+ buf.resize(buf.capacity());
+ // Write up to `capacity` bytes, ignoring the current size.
+ int length = ::vsnprintf(buf.data(), buf.size(), fmt, args);
+ if (length < 0) {
+ buf = error;
+ result = false;
+ goto finish;
+ }
+
+ if (length >= buf.size()) {
+ // The error formatted string didn't fit into our buffer, resize it
+ // to the exact needed size, and retry
+ buf.resize(length + 1);
+ length = ::vsnprintf(buf.data(), buf.size(), fmt, copy_args);
+ if (length < 0) {
+ buf = error;
+ result = false;
+ goto finish;
+ }
+ assert(length < buf.size());
+ }
+ buf.resize(length);
+
+finish:
+ va_end(args);
+ va_end(copy_args);
+ return result;
+}
Modified: lldb/trunk/tools/driver/Driver.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/driver/Driver.h?rev=295368&r1=295367&r2=295368&view=diff
==============================================================================
--- lldb/trunk/tools/driver/Driver.h (original)
+++ lldb/trunk/tools/driver/Driver.h Thu Feb 16 13:38:21 2017
@@ -11,7 +11,7 @@
#define lldb_Driver_h_
#include "Platform.h"
-#include "lldb/Utility/PseudoTerminal.h"
+#include "lldb/Host/PseudoTerminal.h"
#include <bitset>
#include <set>
Modified: lldb/trunk/unittests/Editline/EditlineTest.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/unittests/Editline/EditlineTest.cpp?rev=295368&r1=295367&r2=295368&view=diff
==============================================================================
--- lldb/trunk/unittests/Editline/EditlineTest.cpp (original)
+++ lldb/trunk/unittests/Editline/EditlineTest.cpp Thu Feb 16 13:38:21 2017
@@ -22,8 +22,8 @@
#include "lldb/Core/StringList.h"
#include "lldb/Host/Editline.h"
#include "lldb/Host/Pipe.h"
+#include "lldb/Host/PseudoTerminal.h"
#include "lldb/Utility/Error.h"
-#include "lldb/Utility/PseudoTerminal.h"
namespace {
const size_t TIMEOUT_MILLIS = 5000;
Modified: lldb/trunk/unittests/Utility/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/unittests/Utility/CMakeLists.txt?rev=295368&r1=295367&r2=295368&view=diff
==============================================================================
--- lldb/trunk/unittests/Utility/CMakeLists.txt (original)
+++ lldb/trunk/unittests/Utility/CMakeLists.txt Thu Feb 16 13:38:21 2017
@@ -4,9 +4,9 @@ add_lldb_unittest(UtilityTests
TaskPoolTest.cpp
TimeoutTest.cpp
UriParserTest.cpp
+ VASprintfTest.cpp
LINK_LIBS
- lldbHost
lldbUtility
LINK_COMPONENTS
Support
Added: lldb/trunk/unittests/Utility/VASprintfTest.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/unittests/Utility/VASprintfTest.cpp?rev=295368&view=auto
==============================================================================
--- lldb/trunk/unittests/Utility/VASprintfTest.cpp (added)
+++ lldb/trunk/unittests/Utility/VASprintfTest.cpp Thu Feb 16 13:38:21 2017
@@ -0,0 +1,59 @@
+//===-- VASprintfTest.cpp ---------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Utility/VASprintf.h"
+#include "llvm/ADT/SmallString.h"
+
+#include "gtest/gtest.h"
+
+#include <locale.h>
+
+using namespace lldb_private;
+using namespace llvm;
+
+static bool Sprintf(llvm::SmallVectorImpl<char> &Buffer, const char *Fmt, ...) {
+ va_list args;
+ va_start(args, Fmt);
+ bool Result = VASprintf(Buffer, Fmt, args);
+ va_end(args);
+ return Result;
+}
+
+TEST(VASprintfTest, NoBufferResize) {
+ std::string TestStr("small");
+
+ llvm::SmallString<32> BigBuffer;
+ ASSERT_TRUE(Sprintf(BigBuffer, "%s", TestStr.c_str()));
+ EXPECT_STREQ(TestStr.c_str(), BigBuffer.c_str());
+ EXPECT_EQ(TestStr.size(), BigBuffer.size());
+}
+
+TEST(VASprintfTest, BufferResize) {
+ std::string TestStr("bigger");
+ llvm::SmallString<4> SmallBuffer;
+ ASSERT_TRUE(Sprintf(SmallBuffer, "%s", TestStr.c_str()));
+ EXPECT_STREQ(TestStr.c_str(), SmallBuffer.c_str());
+ EXPECT_EQ(TestStr.size(), SmallBuffer.size());
+}
+
+TEST(VASprintfTest, EncodingError) {
+ // Save the current locale first.
+ std::string Current(::setlocale(LC_ALL, nullptr));
+
+ setlocale(LC_ALL, ".932");
+
+ wchar_t Invalid[2];
+ Invalid[0] = 129;
+ Invalid[1] = 0;
+ llvm::SmallString<32> Buffer;
+ EXPECT_FALSE(Sprintf(Buffer, "%ls", Invalid));
+ EXPECT_EQ("<Encoding error>", Buffer);
+
+ setlocale(LC_CTYPE, Current.c_str());
+}
More information about the lldb-commits
mailing list