//---------------------------------------------------------------------- // This thread's sole purpose is to watch for any status changes in the // child process. //---------------------------------------------------------------------- void *RNBContext::ThreadFunctionProcessStatus(void *arg) { RNBRemoteSP remoteSP(g_remoteSP); RNBRemote *remote = remoteSP.get(); if (remote == NULL) return NULL; RNBContext &ctx = remote->Context(); nub_process_t pid = ctx.ProcessID(); DNBLogThreadedIf(LOG_RNB_PROC, "RNBContext::%s (arg=%p, pid=%4.4x): thread starting...", __FUNCTION__, arg, pid); ctx.Events().SetEvents(RNBContext::event_proc_thread_running); #if defined(__APPLE__) pthread_setname_np("child process status watcher thread"); #if defined(__arm__) || defined(__arm64__) || defined(__aarch64__) struct sched_param thread_param; int thread_sched_policy; if (pthread_getschedparam(pthread_self(), &thread_sched_policy, &thread_param) == 0) { thread_param.sched_priority = 47; pthread_setschedparam(pthread_self(), thread_sched_policy, &thread_param); } #endif #endif bool done = false; while (!done) { DNBLogThreadedIf(LOG_RNB_PROC, "RNBContext::%s calling DNBProcessWaitForEvent(pid, " "eEventProcessRunningStateChanged | " "eEventProcessStoppedStateChanged | eEventStdioAvailable " "| eEventProfileDataAvailable, true)...", __FUNCTION__); nub_event_t pid_status_event = DNBProcessWaitForEvents( pid, eEventProcessRunningStateChanged | eEventProcessStoppedStateChanged | eEventStdioAvailable | eEventProfileDataAvailable, true, NULL); DNBLogThreadedIf(LOG_RNB_PROC, "RNBContext::%s calling DNBProcessWaitForEvent(pid, " "eEventProcessRunningStateChanged | " "eEventProcessStoppedStateChanged | eEventStdioAvailable " "| eEventProfileDataAvailable, true) => 0x%8.8x", __FUNCTION__, pid_status_event); if (pid_status_event == 0) { DNBLogThreadedIf(LOG_RNB_PROC, "RNBContext::%s (pid=%4.4x) got ZERO back " "from DNBProcessWaitForEvent....", __FUNCTION__, pid); // done = true; } else { if (pid_status_event & eEventStdioAvailable) { DNBLogThreadedIf( LOG_RNB_PROC, "RNBContext::%s (pid=%4.4x) got stdio available event....", __FUNCTION__, pid); ctx.Events().SetEvents(RNBContext::event_proc_stdio_available); // Wait for the main thread to consume this notification if it requested // we wait for it ctx.Events().WaitForResetAck(RNBContext::event_proc_stdio_available); } if (pid_status_event & eEventProfileDataAvailable) { DNBLogThreadedIf( LOG_RNB_PROC, "RNBContext::%s (pid=%4.4x) got profile data event....", __FUNCTION__, pid); ctx.Events().SetEvents(RNBContext::event_proc_profile_data); // Wait for the main thread to consume this notification if it requested // we wait for it ctx.Events().WaitForResetAck(RNBContext::event_proc_profile_data); } if (pid_status_event & (eEventProcessRunningStateChanged | eEventProcessStoppedStateChanged)) { nub_state_t pid_state = DNBProcessGetState(pid); DNBLogThreadedIf( LOG_RNB_PROC, "RNBContext::%s (pid=%4.4x) got process state change: %s", __FUNCTION__, pid, DNBStateAsString(pid_state)); // Let the main thread know there is a process state change to see ctx.Events().SetEvents(RNBContext::event_proc_state_changed); // Wait for the main thread to consume this notification if it requested // we wait for it ctx.Events().WaitForResetAck(RNBContext::event_proc_state_changed); switch (pid_state) { case eStateStopped: break; case eStateInvalid: case eStateExited: case eStateDetached: done = true; break; default: break; } } // Reset any events that we consumed. DNBProcessResetEvents(pid, pid_status_event); } } DNBLogThreadedIf(LOG_RNB_PROC, "RNBContext::%s (arg=%p, pid=%4.4x): thread exiting...", __FUNCTION__, arg, pid); ctx.Events().ResetEvents(event_proc_thread_running); ctx.Events().SetEvents(event_proc_thread_exiting); return NULL; }
//---------------------------------------------------------------------- // This thread's sole purpose is to watch for any status changes in the // child process. //---------------------------------------------------------------------- void* RNBContext::ThreadFunctionProcessStatus(void *arg) { RNBRemoteSP remoteSP(g_remoteSP); RNBRemote* remote = remoteSP.get(); if (remote == NULL) return NULL; RNBContext& ctx = remote->Context(); nub_process_t pid = ctx.ProcessID(); DNBLogThreadedIf(LOG_RNB_PROC, "RNBContext::%s (arg=%p, pid=%4.4x): thread starting...", __FUNCTION__, arg, pid); ctx.Events().SetEvents (RNBContext::event_proc_thread_running); bool done = false; while (!done) { DNBLogThreadedIf(LOG_RNB_PROC, "RNBContext::%s calling DNBProcessWaitForEvent(pid, eEventProcessRunningStateChanged | eEventProcessStoppedStateChanged | eEventStdioAvailable, true)...", __FUNCTION__); nub_event_t pid_status_event = DNBProcessWaitForEvents (pid, eEventProcessRunningStateChanged | eEventProcessStoppedStateChanged | eEventStdioAvailable, true, NULL); DNBLogThreadedIf(LOG_RNB_PROC, "RNBContext::%s calling DNBProcessWaitForEvent(pid, eEventProcessRunningStateChanged | eEventProcessStoppedStateChanged | eEventStdioAvailable, true) => 0x%8.8x", __FUNCTION__, pid_status_event); if (pid_status_event == 0) { DNBLogThreadedIf(LOG_RNB_PROC, "RNBContext::%s (pid=%4.4x) got ZERO back from DNBProcessWaitForEvent....", __FUNCTION__, pid); // done = true; } else { if (pid_status_event & eEventStdioAvailable) { DNBLogThreadedIf(LOG_RNB_PROC, "RNBContext::%s (pid=%4.4x) got stdio available event....", __FUNCTION__, pid); ctx.Events().SetEvents (RNBContext::event_proc_stdio_available); // Wait for the main thread to consume this notification if it requested we wait for it ctx.Events().WaitForResetAck(RNBContext::event_proc_stdio_available); } if (pid_status_event & (eEventProcessRunningStateChanged | eEventProcessStoppedStateChanged)) { nub_state_t pid_state = DNBProcessGetState(pid); DNBLogThreadedIf(LOG_RNB_PROC, "RNBContext::%s (pid=%4.4x) got process state change: %s", __FUNCTION__, pid, DNBStateAsString(pid_state)); // Let the main thread know there is a process state change to see ctx.Events().SetEvents (RNBContext::event_proc_state_changed); // Wait for the main thread to consume this notification if it requested we wait for it ctx.Events().WaitForResetAck(RNBContext::event_proc_state_changed); switch (pid_state) { case eStateStopped: break; case eStateInvalid: case eStateExited: case eStateDetached: done = true; break; default: break; } } // Reset any events that we consumed. DNBProcessResetEvents(pid, pid_status_event); } } DNBLogThreadedIf(LOG_RNB_PROC, "RNBContext::%s (arg=%p, pid=%4.4x): thread exiting...", __FUNCTION__, arg, pid); ctx.Events().ResetEvents(event_proc_thread_running); ctx.Events().SetEvents(event_proc_thread_exiting); return NULL; }
//---------------------------------------------------------------------- // Get our program path and arguments from the remote connection. // We will need to start up the remote connection without a PID, get the // arguments, wait for the new process to finish launching and hit its // entry point, and then return the run loop mode that should come next. //---------------------------------------------------------------------- RNBRunLoopMode RNBRunLoopGetStartModeFromRemote (RNBRemoteSP &remoteSP) { std::string packet; if (remoteSP.get() != NULL) { RNBRemote* remote = remoteSP.get(); RNBContext& ctx = remote->Context(); uint32_t event_mask = RNBContext::event_read_packet_available; // Spin waiting to get the A packet. while (1) { DNBLogThreadedIf (LOG_RNB_MAX, "%s ctx.Events().WaitForSetEvents( 0x%08x ) ...",__FUNCTION__, event_mask); nub_event_t set_events = ctx.Events().WaitForSetEvents(event_mask); DNBLogThreadedIf (LOG_RNB_MAX, "%s ctx.Events().WaitForSetEvents( 0x%08x ) => 0x%08x", __FUNCTION__, event_mask, set_events); if (set_events & RNBContext::event_read_packet_available) { rnb_err_t err = rnb_err; RNBRemote::PacketEnum type; err = remote->HandleReceivedPacket (&type); // check if we tried to attach to a process if (type == RNBRemote::vattach || type == RNBRemote::vattachwait) { if (err == rnb_success) return eRNBRunLoopModeInferiorExecuting; else { RNBLogSTDERR ("error: attach failed."); return eRNBRunLoopModeExit; } } if (err == rnb_success) { DNBLogThreadedIf (LOG_RNB_MINIMAL, "%s Got success...",__FUNCTION__); continue; } else if (err == rnb_not_connected) { RNBLogSTDERR ("error: connection lost."); return eRNBRunLoopModeExit; } else { // a catch all for any other gdb remote packets that failed DNBLogThreadedIf (LOG_RNB_MINIMAL, "%s Error getting packet.",__FUNCTION__); continue; } DNBLogThreadedIf (LOG_RNB_MINIMAL, "#### %s", __FUNCTION__); } else { DNBLogThreadedIf (LOG_RNB_MINIMAL, "%s Connection closed before getting \"A\" packet.", __FUNCTION__); return eRNBRunLoopModeExit; } } } return eRNBRunLoopModeExit; }