diff options
Diffstat (limited to 'tools/lldb-mi/MICmnStreamStdinLinux.cpp')
-rw-r--r-- | tools/lldb-mi/MICmnStreamStdinLinux.cpp | 307 |
1 files changed, 160 insertions, 147 deletions
diff --git a/tools/lldb-mi/MICmnStreamStdinLinux.cpp b/tools/lldb-mi/MICmnStreamStdinLinux.cpp index f73dc32d8258..07e652d84c19 100644 --- a/tools/lldb-mi/MICmnStreamStdinLinux.cpp +++ b/tools/lldb-mi/MICmnStreamStdinLinux.cpp @@ -8,22 +8,22 @@ //===----------------------------------------------------------------------===// //++ -// File: MIUtilStreamStdin.cpp +// File: MIUtilStreamStdin.cpp // -// Overview: CMICmnStreamStdinLinux implementation. +// Overview: CMICmnStreamStdinLinux implementation. // -// Environment: Compilers: Visual C++ 12. -// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 -// Libraries: See MIReadmetxt. +// Environment: Compilers: Visual C++ 12. +// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 +// Libraries: See MIReadmetxt. // -// Copyright: None. +// Copyright: None. //-- // Third Party Headers: -#if !defined( _MSC_VER ) +#if defined(__APPLE__) #include <sys/select.h> -#include <termios.h> -#endif // !defined( _MSC_VER ) +#include <unistd.h> // For STDIN_FILENO +#endif // defined( __APPLE__ ) #include <string.h> // For std::strerror() // In-house headers: @@ -33,180 +33,193 @@ #include "MIUtilSingletonHelper.h" //++ ------------------------------------------------------------------------------------ -// Details: CMICmnStreamStdinLinux constructor. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmnStreamStdinLinux constructor. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmnStreamStdinLinux::CMICmnStreamStdinLinux( void ) -: m_constBufferSize( 1024 ) -, m_pStdin( nullptr ) -, m_pCmdBuffer( nullptr ) +CMICmnStreamStdinLinux::CMICmnStreamStdinLinux(void) + : m_constBufferSize(1024) + , m_pStdin(nullptr) + , m_pCmdBuffer(nullptr) { } //++ ------------------------------------------------------------------------------------ -// Details: CMICmnStreamStdinLinux destructor. -// Type: Overridable. -// Args: None. -// Return: None. -// Throws: None. +// Details: CMICmnStreamStdinLinux destructor. +// Type: Overridable. +// Args: None. +// Return: None. +// Throws: None. //-- -CMICmnStreamStdinLinux::~CMICmnStreamStdinLinux( void ) +CMICmnStreamStdinLinux::~CMICmnStreamStdinLinux(void) { - Shutdown(); + Shutdown(); } //++ ------------------------------------------------------------------------------------ -// Details: Initialize resources for *this Stdin stream. -// Type: Method. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Initialize resources for *this Stdin stream. +// Type: Method. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmnStreamStdinLinux::Initialize( void ) +bool +CMICmnStreamStdinLinux::Initialize(void) { - if( m_bInitialized ) - return MIstatus::success; - - bool bOk = MIstatus::success; - CMIUtilString errMsg; - - // Note initialisation order is important here as some resources depend on previous - MI::ModuleInit< CMICmnLog > ( IDS_MI_INIT_ERR_LOG , bOk, errMsg ); - MI::ModuleInit< CMICmnResources >( IDS_MI_INIT_ERR_RESOURCES, bOk, errMsg ); - - // Other resources required - if( bOk ) - { - m_pCmdBuffer = new MIchar[ m_constBufferSize ]; - m_pStdin = stdin; - } - - // Clear error indicators for std input - ::clearerr( stdin ); - - m_bInitialized = bOk; - - if( !bOk ) - { - CMIUtilString strInitError( CMIUtilString::Format( MIRSRC( IDS_MI_INIT_ERR_OS_STDIN_HANDLER ), errMsg.c_str() ) ); - SetErrorDescription( strInitError ); - return MIstatus::failure; - } - - return MIstatus::success; + if (m_bInitialized) + return MIstatus::success; + + bool bOk = MIstatus::success; + CMIUtilString errMsg; + + // Note initialisation order is important here as some resources depend on previous + MI::ModuleInit<CMICmnLog>(IDS_MI_INIT_ERR_LOG, bOk, errMsg); + MI::ModuleInit<CMICmnResources>(IDS_MI_INIT_ERR_RESOURCES, bOk, errMsg); + + // Other resources required + if (bOk) + { + m_pCmdBuffer = new MIchar[m_constBufferSize]; + m_pStdin = stdin; + } + + // Clear error indicators for std input + ::clearerr(stdin); + + m_bInitialized = bOk; + + if (!bOk) + { + CMIUtilString strInitError(CMIUtilString::Format(MIRSRC(IDS_MI_INIT_ERR_OS_STDIN_HANDLER), errMsg.c_str())); + SetErrorDescription(strInitError); + return MIstatus::failure; + } + + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Release resources for *this Stdin stream. -// Type: Method. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Release resources for *this Stdin stream. +// Type: Method. +// Args: None. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmnStreamStdinLinux::Shutdown( void ) +bool +CMICmnStreamStdinLinux::Shutdown(void) { - if( !m_bInitialized ) - return MIstatus::success; + if (!m_bInitialized) + return MIstatus::success; - m_bInitialized = false; + m_bInitialized = false; - ClrErrorDescription(); + ClrErrorDescription(); - bool bOk = MIstatus::success; - CMIUtilString errMsg; + bool bOk = MIstatus::success; + CMIUtilString errMsg; - // Tidy up - if( m_pCmdBuffer != nullptr ) - { - delete [] m_pCmdBuffer; - m_pCmdBuffer = nullptr; - } - m_pStdin = nullptr; + // Tidy up + if (m_pCmdBuffer != nullptr) + { + delete[] m_pCmdBuffer; + m_pCmdBuffer = nullptr; + } + m_pStdin = nullptr; - // Note shutdown order is important here - MI::ModuleShutdown< CMICmnResources >( IDS_MI_INIT_ERR_RESOURCES, bOk, errMsg ); - MI::ModuleShutdown< CMICmnLog > ( IDS_MI_INIT_ERR_LOG , bOk, errMsg ); + // Note shutdown order is important here + MI::ModuleShutdown<CMICmnResources>(IDS_MI_INIT_ERR_RESOURCES, bOk, errMsg); + MI::ModuleShutdown<CMICmnLog>(IDS_MI_INIT_ERR_LOG, bOk, errMsg); - if( !bOk ) - { - SetErrorDescriptionn( MIRSRC( IDS_MI_SHTDWN_ERR_OS_STDIN_HANDLER ), errMsg.c_str() ); - } + if (!bOk) + { + SetErrorDescriptionn(MIRSRC(IDS_MI_SHTDWN_ERR_OS_STDIN_HANDLER), errMsg.c_str()); + } - return MIstatus::success; -} + return MIstatus::success; +} //++ ------------------------------------------------------------------------------------ -// Details: Determine if stdin has any characters present in its buffer. -// Type: Method. -// Args: vwbAvail - (W) True = There is chars available, false = nothing there. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. +// Details: Determine if stdin has any characters present in its buffer. +// Type: Method. +// Args: vwbAvail - (W) True = There is chars available, false = nothing there. +// Return: MIstatus::success - Functional succeeded. +// MIstatus::failure - Functional failed. +// Throws: None. //-- -bool CMICmnStreamStdinLinux::InputAvailable( bool & vwbAvail ) +bool +CMICmnStreamStdinLinux::InputAvailable(bool &vwbAvail) { -/* AD: Not used ATM but could come in handy just in case we need to do - this, poll for input - - static const int STDIN = 0; - static bool bInitialized = false; - - if( !bInitialized ) - { - // Use termios to turn off line buffering - ::termios term; - ::tcgetattr( STDIN, &term ); - ::term.c_lflag &= ~ICANON; - ::tcsetattr( STDIN, TCSANOW, &term ); - ::setbuf( stdin, NULL ); - bInitialized = true; +#if defined(__APPLE__) + // The code below is needed on OSX where lldb-mi hangs when doing -exec-run. + // The hang seems to come from calling fgets and fileno from different thread. + // Although this problem was not observed on Linux. + // A solution based on 'ioctl' was initially committed but it seems to make + // lldb-mi takes much more processor time. The solution based on 'select' works + // well but it seems to slow the execution of lldb-mi tests a lot on Linux. + // As a result, this code is #defined to run only on OSX. + fd_set setOfStdin; + FD_ZERO(&setOfStdin); + FD_SET(STDIN_FILENO, &setOfStdin); + + // Wait while input would be available + if (::select(STDIN_FILENO + 1, &setOfStdin, nullptr, nullptr, nullptr) == -1) + { + vwbAvail = false; + return MIstatus::failure; } - int nBytesWaiting; - ::ioctl( STDIN, FIONREAD, &nBytesWaiting ); - vwbAvail = (nBytesWaiting > 0); - - return MIstatus::success; -*/ - - return MIstatus::success; +#endif // defined( __APPLE__ ) + vwbAvail = true; + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ -// Details: Wait on new line of data from stdin stream (completed by '\n' or '\r'). -// Type: Method. -// Args: vwErrMsg - (W) Empty string ok or error description. -// Return: MIchar * - text buffer pointer or NULL on failure. -// Throws: None. +// Details: Wait on new line of data from stdin stream (completed by '\n' or '\r'). +// Type: Method. +// Args: vwErrMsg - (W) Empty string ok or error description. +// Return: MIchar * - text buffer pointer or NULL on failure. +// Throws: None. //-- -const MIchar * CMICmnStreamStdinLinux::ReadLine( CMIUtilString & vwErrMsg ) +const MIchar * +CMICmnStreamStdinLinux::ReadLine(CMIUtilString &vwErrMsg) { - vwErrMsg.clear(); - - // Read user input - const MIchar * pText = ::fgets( &m_pCmdBuffer[ 0 ], m_constBufferSize, stdin ); - if( pText == nullptr ) - { - if( ::ferror( m_pStdin ) != 0 ) - vwErrMsg = ::strerror( errno ); - return nullptr; - } + vwErrMsg.clear(); + + // Read user input + const MIchar *pText = ::fgets(&m_pCmdBuffer[0], m_constBufferSize, stdin); + if (pText == nullptr) + { + if (::ferror(m_pStdin) != 0) + vwErrMsg = ::strerror(errno); + return nullptr; + } // Strip off new line characters - for( MIchar * pI = m_pCmdBuffer; *pI != '\0'; pI++ ) - { - if( (*pI == '\n') || (*pI == '\r') ) - { - *pI = '\0'; - break; - } - } - - return pText; + for (MIchar *pI = m_pCmdBuffer; *pI != '\0'; pI++) + { + if ((*pI == '\n') || (*pI == '\r')) + { + *pI = '\0'; + break; + } + } + + return pText; } +//++ ------------------------------------------------------------------------------------ +// Details: Interrupt current and prevent new ReadLine operations. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. +//-- +void +CMICmnStreamStdinLinux::InterruptReadLine(void) +{ + fclose(stdin); +} |