ErrorCode Process::wait(int *rstatus) { int status, signal; ProcessInfo info; ErrorCode err; pid_t tid; // We have at least one thread when we start waiting on a process. DS2ASSERT(!_threads.empty()); continue_waiting: err = super::wait(&status); if (err != kSuccess) return err; DS2LOG(Debug, "stopped: status=%d", status); if (WIFEXITED(status)) { err = super::wait(&status); DS2LOG(Debug, "exited: status=%d", status); _currentThread->updateStopInfo(status); _terminated = true; if (rstatus != nullptr) { *rstatus = status; } return kSuccess; } DS2BUG("not implemented"); switch (_currentThread->_stopInfo.event) { case StopInfo::kEventNone: switch (_currentThread->_stopInfo.reason) { case StopInfo::kReasonNone: ptrace().resume(ProcessThreadId(_pid, tid), info); goto continue_waiting; default: DS2ASSERT(false); goto continue_waiting; } case StopInfo::kEventExit: case StopInfo::kEventKill: DS2LOG(Debug, "thread %d is exiting", tid); // // Killing the main thread? // // Note(sas): This might be buggy; the main thread exiting // doesn't mean that the process is dying. // if (tid == _pid && _threads.size() == 1) { DS2LOG(Debug, "last thread is exiting"); break; } // // Remove and release the thread associated with this pid. // removeThread(tid); goto continue_waiting; case StopInfo::kEventStop: if (getInfo(info) != kSuccess) { DS2LOG(Error, "couldn't get process info for pid %d", _pid); goto continue_waiting; } signal = _currentThread->_stopInfo.signal; if (signal == SIGSTOP || signal == SIGCHLD) { // // Silently ignore SIGSTOP, SIGCHLD and SIGRTMIN (this // last one used for thread cancellation) and continue. // // Note(oba): The SIGRTMIN defines expands to a glibc // call, this due to the fact the POSIX standard does // not mandate that SIGRT* defines to be user-land // constants. // // Note(sas): This is probably partially dead code as // ptrace().step() doesn't work on ARM. // // Note(sas): Single-step detection should be higher up, not // only for SIGSTOP, SIGCHLD and SIGRTMIN, but for every // signal that we choose to ignore. // bool stepping = (_currentThread->state() == Thread::kStepped); if (signal == SIGSTOP) { signal = 0; } else { DS2LOG(Debug, "%s due to special signal, tid=%d status=%#x signal=%s", stepping ? "stepping" : "resuming", tid, status, strsignal(signal)); } ErrorCode error; if (stepping) { error = ptrace().step(ProcessThreadId(_pid, tid), info, signal); } else { error = ptrace().resume(ProcessThreadId(_pid, tid), info, signal); } if (error != kSuccess) { DS2LOG(Warning, "cannot resume thread %d error=%d", tid, error); } goto continue_waiting; } else if (_passthruSignals.find(signal) != _passthruSignals.end()) { ptrace().resume(ProcessThreadId(_pid, tid), info, signal); goto continue_waiting; } else { // // This is a signal that we want to transmit back to the // debugger. // break; } } if (!(WIFEXITED(status) || WIFSIGNALED(status))) { // // Suspend the process, this must be done after updating // the thread trap info. // suspend(); } if ((WIFEXITED(status) || WIFSIGNALED(status))) { _terminated = true; } if (rstatus != nullptr) { *rstatus = status; } return kSuccess; }
std::string Platform::GetThreadName(ProcessId pid, ThreadId tid) { return Host::Darwin::LibProc::GetThreadName(ProcessThreadId(pid, tid)); }