bool PCEventHandler::handle_internal(EventPtr ev) { proccontrol_printf("%s[%d]: attempting to handle event %s on thread %d/%d\n", FILE__, __LINE__, ev->getEventType().name().c_str(), (ev->getProcess() ? ev->getProcess()->getPid() : -1), (ev->getThread() ? ev->getThread()->getLWP() : (Dyninst::LWP)-1)); if(!ev->getProcess()) { proccontrol_printf("%s[%d]: Event received w/o associated ProcControl process object, treating as handled successfully\n", FILE__, __LINE__); return true; } PCProcess *evProc = static_cast<PCProcess *>(ev->getProcess()->getData()); if( evProc == NULL ) { proccontrol_printf("%s[%d]: ERROR: handle to Dyninst process is invalid\n", FILE__, __LINE__); return true; } if( !( ev->getEventType().code() == EventType::ForceTerminate || ev->getEventType().code() == EventType::Crash || ev->getEventType().code() == EventType::Exit ) ) { // This means we already saw the entry to exit event and we can no longer // operate on the process, so ignore the event if( evProc->isTerminated() ) { proccontrol_printf("%s[%d]: process already marked terminated, ignoring event\n", FILE__, __LINE__); // Still need to make sure ProcControl runs the process until it exits if( !ev->getProcess()->isTerminated() ) { Process::ptr tmpProc(pc_const_cast<Process>(ev->getProcess())); if( !tmpProc->continueProc() ) { proccontrol_printf("%s[%d]: failed to continue exiting process\n", FILE__, __LINE__); } } return true; } // The process needs to be stopped so we can operate on it if( !evProc->isStopped() ) { proccontrol_printf("%s[%d]: stopping process for event handling\n", FILE__, __LINE__); if( !evProc->stopProcess() ) { proccontrol_printf("%s[%d]: failed to stop process for event handling\n", FILE__, __LINE__); return false; } } } // Need to save state because we could be called recursively bool prevEventHandlingState = evProc->isInEventHandling(); evProc->setInEventHandling(true); bool ret = true; switch(ev->getEventType().code()) { // Errors first case EventType::Error: case EventType::Unset: ret = false; break; case EventType::SingleStep: // for now, this should be unused if( !evProc->isInDebugSuicide() ) ret = false; break; // for now these events are skipped case EventType::Bootstrap: case EventType::Stop: break; // Interesting events case EventType::Exit: ret = handleExit(ev->getEventExit(), evProc); break; case EventType::Crash: ret = handleCrash(ev->getEventCrash(), evProc); break; case EventType::ForceTerminate: ret = handleForceTerminate(ev->getEventForceTerminate(), evProc); break; case EventType::Fork: ret = handleFork(ev->getEventFork(), evProc); break; case EventType::Exec: // On Post-Exec, a new PCProcess is created ret = handleExec(ev->getEventExec(), evProc); break; case EventType::UserThreadCreate: case EventType::LWPCreate: case EventType::ThreadCreate: ret = handleThreadCreate(ev->getEventNewThread(), evProc); break; case EventType::UserThreadDestroy: case EventType::LWPDestroy: case EventType::ThreadDestroy: ret = handleThreadDestroy(ev->getEventThreadDestroy(), evProc); break; case EventType::Signal: ret = handleSignal(ev->getEventSignal(), evProc); break; case EventType::Breakpoint: ret = handleBreakpoint(ev->getEventBreakpoint(), evProc); break; case EventType::LibraryLoad: case EventType::LibraryUnload: case EventType::Library: ret = handleLibrary(ev->getEventLibrary(), evProc); break; case EventType::RPC: ret = handleRPC(ev->getEventRPC(), evProc); break; default: proccontrol_printf("%s[%d]: ignoring unknown event: %s\n", FILE__, __LINE__, ev->getEventType().name().c_str()); break; } //evProc->decPendingEvents(); evProc->setInEventHandling(prevEventHandlingState); if( dyn_debug_proccontrol ) { proccontrol_printf("%s[%d]: continue condition ( %d %d %d %d %d %d )\n", FILE__, __LINE__, (int) ret, (int) (evProc->getDesiredProcessState() == PCProcess::ps_running), (int) evProc->isStopped(), (int) !evProc->hasReportedEvent(), (int) !evProc->isTerminated(), (int) !evProc->hasPendingEvents()); } if(ret // there were no errors && evProc->getDesiredProcessState() == PCProcess::ps_running // the user wants the process running && evProc->isStopped() // the process is stopped && !evProc->hasReportedEvent() // we aren't in the middle of processing an event that we reported to ProcControl && !evProc->isTerminated() // If one of the handling routines has marked the process exited && !evProc->hasPendingEvents() // Can't continue the process until all pending events handled for all threads ) { proccontrol_printf("%s[%d]: user wants process running after event handling\n", FILE__, __LINE__); if( evProc->hasRunningSyncRPC() ) { if( !evProc->continueSyncRPCThreads() ) { proccontrol_printf("%s[%d]: failed to continue thread after event handling\n", FILE__, __LINE__); ret = false; } }else{ proccontrol_printf("%s[%d]: continuing entire process\n", FILE__, __LINE__); if( !evProc->continueProcess() ) { proccontrol_printf("%s[%d]: failed to continue process after event handling\n", FILE__, __LINE__); ret = false; } } } else { proccontrol_printf("%s[%d]: delaying process continue: %s %s %s %s %s %s\n", FILE__, __LINE__, (ret ? "<return success>" : "<return failure>"), ((evProc->getDesiredProcessState() == PCProcess::ps_running) ? "<desired running>" : "<desired stop>"), (evProc->isStopped() ? "<stopped>" : "<running>"), (evProc->hasReportedEvent() ? "<reported event>" : "<no reported event>"), (evProc->isTerminated() ? "<terminated>" : "<not terminated>"), (evProc->hasPendingEvents() ? "<pending events>" : "<no pending events>")); } if( evProc->isExiting() ) { proccontrol_printf("%s[%d]: pending exit reported to BPatch-level, marking process exited\n", FILE__, __LINE__); evProc->markExited(); } proccontrol_printf("%s[%d]: finished handling event: %s (err = %s)\n", FILE__, __LINE__, ev->getEventType().name().c_str(), !ret ? "true" : "false"); return ret; }