//---------------------------------------------------------------------- // 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; }
//---------------------------------------------------------------------- // 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; }