forked from OSchip/llvm-project
				
			Allow debugserver to detach from the target if the connection is
unexpectedly closed. llvm-svn: 202110
This commit is contained in:
		
							parent
							
								
									47ff9ab1be
								
							
						
					
					
						commit
						5881318c88
					
				| 
						 | 
					@ -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;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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 ();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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();
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue