Example #1
0
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;
}