Allow debugserver to detach from the target if the connection is

unexpectedly closed.

llvm-svn: 202110
This commit is contained in:
Jim Ingham 2014-02-25 04:53:13 +00:00
parent 47ff9ab1be
commit 5881318c88
5 changed files with 43 additions and 7 deletions

View File

@ -650,6 +650,10 @@ DNBProcessDetach (nub_process_t pid)
MachProcessSP procSP; MachProcessSP procSP;
if (GetProcessSP (pid, procSP)) if (GetProcessSP (pid, procSP))
{ {
const bool remove = true;
DNBLogThreaded("Disabling breakpoints and watchpoints, and detaching from %d.", pid);
procSP->DisableAllBreakpoints(remove);
procSP->DisableAllWatchpoints (remove);
return procSP->Detach(); return procSP->Detach();
} }
return false; return false;

View File

@ -307,14 +307,16 @@ MachProcess::SetState(nub_state_t new_state)
} }
void void
MachProcess::Clear() MachProcess::Clear(bool detaching)
{ {
// Clear any cached thread list while the pid and task are still valid // Clear any cached thread list while the pid and task are still valid
m_task.Clear(); m_task.Clear();
// Now clear out all member variables // Now clear out all member variables
m_pid = INVALID_NUB_PROCESS; m_pid = INVALID_NUB_PROCESS;
CloseChildFileDescriptors(); if (!detaching)
CloseChildFileDescriptors();
m_path.clear(); m_path.clear();
m_args.clear(); m_args.clear();
SetState(eStateUnloaded); SetState(eStateUnloaded);
@ -554,7 +556,8 @@ MachProcess::Detach()
m_task.Clear(); m_task.Clear();
// Clear out any notion of the process we once were // Clear out any notion of the process we once were
Clear(); const bool detaching = true;
Clear(detaching);
SetState(eStateDetached); SetState(eStateDetached);

View File

@ -258,7 +258,7 @@ private:
eMachProcessFlagsAttached = (1 << 0), eMachProcessFlagsAttached = (1 << 0),
eMachProcessFlagsUsingSBS = (1 << 1) eMachProcessFlagsUsingSBS = (1 << 1)
}; };
void Clear (); void Clear (bool detaching = false);
void ReplyToAllExceptions (); void ReplyToAllExceptions ();
void PrivateResume (); void PrivateResume ();

View File

@ -57,7 +57,8 @@ public:
m_pid_pthread(), m_pid_pthread(),
m_launch_status(), m_launch_status(),
m_arg_vec (), m_arg_vec (),
m_env_vec () m_env_vec (),
m_detach_on_error(false)
{ {
} }
@ -116,6 +117,10 @@ public:
const char * GetSTDOUTPath() { return m_stdout.empty() ? NULL : m_stdout.c_str(); } const char * GetSTDOUTPath() { return m_stdout.empty() ? NULL : m_stdout.c_str(); }
const char * GetSTDERRPath() { return m_stderr.empty() ? NULL : m_stderr.c_str(); } const char * GetSTDERRPath() { return m_stderr.empty() ? NULL : m_stderr.c_str(); }
const char * GetWorkingDirPath() { return m_working_dir.empty() ? NULL : m_working_dir.c_str(); } const char * GetWorkingDirPath() { return m_working_dir.empty() ? NULL : m_working_dir.c_str(); }
void SetDetachOnError(bool detach) { m_detach_on_error = detach; }
bool GetDetachOnError () { return m_detach_on_error; }
protected: protected:
//------------------------------------------------------------------ //------------------------------------------------------------------
// Classes that inherit from RNBContext can see and modify these // Classes that inherit from RNBContext can see and modify these
@ -133,6 +138,7 @@ protected:
std::vector<std::string> m_arg_vec; std::vector<std::string> m_arg_vec;
std::vector<std::string> m_env_vec; // This will be unparsed - entries FOO=value std::vector<std::string> m_env_vec; // This will be unparsed - entries FOO=value
std::string m_working_directory; std::string m_working_directory;
bool m_detach_on_error;
void StartProcessStatusThread(); void StartProcessStatusThread();
void StopProcessStatusThread(); void StopProcessStatusThread();

View File

@ -63,6 +63,7 @@ static nub_launch_flavor_t g_launch_flavor = eLaunchFlavorDefault;
int g_disable_aslr = 0; int g_disable_aslr = 0;
int g_isatty = 0; int g_isatty = 0;
bool g_detach_on_error = false;
#define RNBLogSTDOUT(fmt, ...) do { if (g_isatty) { fprintf(stdout, fmt, ## __VA_ARGS__); } else { _DNBLog(0, fmt, ## __VA_ARGS__); } } while (0) #define RNBLogSTDOUT(fmt, ...) do { if (g_isatty) { fprintf(stdout, fmt, ## __VA_ARGS__); } else { _DNBLog(0, fmt, ## __VA_ARGS__); } } while (0)
#define RNBLogSTDERR(fmt, ...) do { if (g_isatty) { fprintf(stderr, fmt, ## __VA_ARGS__); } else { _DNBLog(0, fmt, ## __VA_ARGS__); } } while (0) #define RNBLogSTDERR(fmt, ...) do { if (g_isatty) { fprintf(stderr, fmt, ## __VA_ARGS__); } else { _DNBLog(0, fmt, ## __VA_ARGS__); } } while (0)
@ -571,8 +572,24 @@ RNBRunLoopInferiorExecuting (RNBRemote *remote)
// in its current state and listen for another connection... // in its current state and listen for another connection...
if (ctx.ProcessStateRunning()) if (ctx.ProcessStateRunning())
{ {
DNBLog ("debugserver's event read thread is exiting, killing the inferior process."); if (ctx.GetDetachOnError())
DNBProcessKill (ctx.ProcessID()); {
DNBLog ("debugserver's event read thread is exiting, detaching from the inferior process.");
DNBProcessDetach (ctx.ProcessID());
}
else
{
DNBLog ("debugserver's event read thread is exiting, killing the inferior process.");
DNBProcessKill (ctx.ProcessID());
}
}
else
{
if (ctx.GetDetachOnError())
{
DNBLog ("debugserver's event read thread is exiting, detaching from the inferior process.");
DNBProcessDetach (ctx.ProcessID());
}
} }
} }
mode = eRNBRunLoopModeExit; mode = eRNBRunLoopModeExit;
@ -814,6 +831,7 @@ static struct option g_long_options[] =
{ "attach", required_argument, NULL, 'a' }, { "attach", required_argument, NULL, 'a' },
{ "arch", required_argument, NULL, 'A' }, { "arch", required_argument, NULL, 'A' },
{ "debug", no_argument, NULL, 'g' }, { "debug", no_argument, NULL, 'g' },
{ "detach-on-error", no_argument, NULL, 'e' },
{ "verbose", no_argument, NULL, 'v' }, { "verbose", no_argument, NULL, 'v' },
{ "lockdown", no_argument, &g_lockdown_opt, 1 }, // short option "-k" { "lockdown", no_argument, &g_lockdown_opt, 1 }, // short option "-k"
{ "applist", no_argument, &g_applist_opt, 1 }, // short option "-t" { "applist", no_argument, &g_applist_opt, 1 }, // short option "-t"
@ -1011,6 +1029,9 @@ main (int argc, char *argv[])
} }
} }
break; break;
case 'e':
g_detach_on_error = true;
case 'W': case 'W':
if (optarg && optarg[0]) if (optarg && optarg[0])
@ -1181,6 +1202,8 @@ main (int argc, char *argv[])
} }
} }
remote->Context().SetDetachOnError(g_detach_on_error);
remote->Initialize(); remote->Initialize();
// It is ok for us to set NULL as the logfile (this will disable any logging) // It is ok for us to set NULL as the logfile (this will disable any logging)