Added a SBListener parameter to Launch and attach calls to avoid a race

condition that could occur when launching or attaching. What could happen is
you would launch/attach to a process, then you would need to tell a listener
to watch for process state changed events. In this case, if you waited too
long to listen for events, you could miss the initial stop event, requiring
clients to listen, then check the process state. 

llvm-svn: 124818
This commit is contained in:
Greg Clayton 2011-02-03 21:28:34 +00:00
parent ce8661608b
commit 4b0456211c
4 changed files with 133 additions and 7 deletions

View File

@ -108,6 +108,9 @@ private:
lldb_private::Listener *
get() const;
lldb_private::Listener &
ref() const;
lldb_private::Listener &
operator *();

View File

@ -54,8 +54,60 @@ public:
lldb::SBProcess
GetProcess ();
//------------------------------------------------------------------
/// Launch a new process.
///
/// Launch a new process by spawning a new process using the
/// target object's executable module's file as the file to launch.
/// Arguments are given in \a argv, and the environment variables
/// are in \a envp. Standard input and output files can be
/// optionally re-directed to \a stdin_path, \a stdout_path, and
/// \a stderr_path.
///
/// @param[in] listener
/// An optional listener that will receive all process events.
/// If \a listener is valid then \a listener will listen to all
/// process events. If not valid, then this target's debugger
/// (SBTarget::GetDebugger()) will listen to all process events.
///
/// @param[in] argv
/// The argument array.
///
/// @param[in] envp
/// The environment array.
///
/// @param[in] launch_flags
/// Flags to modify the launch (@see lldb::LaunchFlags)
///
/// @param[in] stdin_path
/// The path to use when re-directing the STDIN of the new
/// process. If all stdXX_path arguments are NULL, a pseudo
/// terminal will be used.
///
/// @param[in] stdout_path
/// The path to use when re-directing the STDOUT of the new
/// process. If all stdXX_path arguments are NULL, a pseudo
/// terminal will be used.
///
/// @param[in] stderr_path
/// The path to use when re-directing the STDERR of the new
/// process. If all stdXX_path arguments are NULL, a pseudo
/// terminal will be used.
///
/// @param[in] working_directory
/// The working directory to have the child process run in
///
/// @param[in] launch_flags
/// Some launch options specified by logical OR'ing
/// lldb::LaunchFlags enumeration values together.
///
/// @return
/// An error object. Call GetID() to get the process ID if
/// the error object is success.
//------------------------------------------------------------------
lldb::SBProcess
Launch (char const **argv,
Launch (SBListener &listener,
char const **argv,
char const **envp,
const char *stdin_path,
const char *stdout_path,
@ -65,12 +117,65 @@ public:
bool stop_at_entry,
lldb::SBError& error);
//------------------------------------------------------------------
/// Launch a new process.
///
/// Launch a new process by spawning a new process using the
/// target object's executable module's file as the file to launch.
/// Arguments are given in \a argv, and the environment variables
/// are in \a envp. Standard input and output files can be
/// optionally re-directed to \a stdin_path, \a stdout_path, and
/// \a stderr_path.
///
/// @param[in] listener
/// An optional listener that will receive all process events.
/// If NULL, then the this target's debugger (SBTarget::GetDebugger())
/// will listen to all process events. If non-NULL, \a listener
/// will listen to all process events.
///
/// @param[in] argv
/// The argument array.
///
/// @param[in] envp
/// The environment array.
///
/// @param[in] launch_flags
/// Flags to modify the launch (@see lldb::LaunchFlags)
///
/// @param[in] stdin_path
/// The path to use when re-directing the STDIN of the new
/// process. If all stdXX_path arguments are NULL, a pseudo
/// terminal will be used.
///
/// @param[in] stdout_path
/// The path to use when re-directing the STDOUT of the new
/// process. If all stdXX_path arguments are NULL, a pseudo
/// terminal will be used.
///
/// @param[in] stderr_path
/// The path to use when re-directing the STDERR of the new
/// process. If all stdXX_path arguments are NULL, a pseudo
/// terminal will be used.
///
/// @param[in] working_directory
/// The working directory to have the child process run in
///
/// @param[in] launch_flags
/// Some launch options specified by logical OR'ing
/// lldb::LaunchFlags enumeration values together.
///
/// @return
/// An error object. Call GetID() to get the process ID if
/// the error object is success.
//------------------------------------------------------------------
lldb::SBProcess
AttachToProcessWithID (lldb::pid_t pid, // The process ID to attach to
AttachToProcessWithID (SBListener &listener,
lldb::pid_t pid, // The process ID to attach to
lldb::SBError& error); // An error explaining what went wrong if attach fails
lldb::SBProcess
AttachToProcessWithName (const char *name, // basename of process to attach to
AttachToProcessWithName (SBListener &listener,
const char *name, // basename of process to attach to
bool wait_for, // if true wait for a new instance of "name" to be launched
lldb::SBError& error); // An error explaining what went wrong if attach fails

View File

@ -386,6 +386,11 @@ SBListener::reset(Listener *listener, bool owns)
m_opaque_ptr = listener;
}
Listener &
SBListener::ref() const
{
return *m_opaque_ptr;
}
Listener &
SBListener::operator *()

View File

@ -121,6 +121,7 @@ SBTarget::GetDebugger () const
SBProcess
SBTarget::Launch
(
SBListener &listener,
char const **argv,
char const **envp,
const char *stdin_path,
@ -218,7 +219,7 @@ SBTarget::Launch
if (pid != LLDB_INVALID_PROCESS_ID)
{
sb_process = AttachToProcessWithID(pid, error);
sb_process = AttachToProcessWithID(listener, pid, error);
}
else
{
@ -237,7 +238,10 @@ SBTarget::Launch
}
else
{
sb_process.SetProcess (m_opaque_sp->CreateProcess (m_opaque_sp->GetDebugger().GetListener()));
if (listener.IsValid())
sb_process.SetProcess (m_opaque_sp->CreateProcess (listener.ref()));
else
sb_process.SetProcess (m_opaque_sp->CreateProcess (m_opaque_sp->GetDebugger().GetListener()));
if (sb_process.IsValid())
{
@ -294,6 +298,7 @@ SBTarget::Launch
lldb::SBProcess
SBTarget::AttachToProcessWithID
(
SBListener &listener,
lldb::pid_t pid,// The process ID to attach to
SBError& error // An error explaining what went wrong if attach fails
)
@ -302,7 +307,11 @@ SBTarget::AttachToProcessWithID
if (m_opaque_sp)
{
Mutex::Locker api_locker (m_opaque_sp->GetAPIMutex());
sb_process.SetProcess (m_opaque_sp->CreateProcess (m_opaque_sp->GetDebugger().GetListener()));
if (listener.IsValid())
sb_process.SetProcess (m_opaque_sp->CreateProcess (listener.ref()));
else
sb_process.SetProcess (m_opaque_sp->CreateProcess (m_opaque_sp->GetDebugger().GetListener()));
if (sb_process.IsValid())
{
@ -324,6 +333,7 @@ SBTarget::AttachToProcessWithID
lldb::SBProcess
SBTarget::AttachToProcessWithName
(
SBListener &listener,
const char *name, // basename of process to attach to
bool wait_for, // if true wait for a new instance of "name" to be launched
SBError& error // An error explaining what went wrong if attach fails
@ -334,7 +344,10 @@ SBTarget::AttachToProcessWithName
{
Mutex::Locker api_locker (m_opaque_sp->GetAPIMutex());
sb_process.SetProcess (m_opaque_sp->CreateProcess (m_opaque_sp->GetDebugger().GetListener()));
if (listener.IsValid())
sb_process.SetProcess (m_opaque_sp->CreateProcess (listener.ref()));
else
sb_process.SetProcess (m_opaque_sp->CreateProcess (m_opaque_sp->GetDebugger().GetListener()));
if (sb_process.IsValid())
{