Example #1
0
DysectAPI::DysectErrorCode Backend::handleTimerActions() {
  pthread_mutex_lock(&probesPendingActionMutex);
  if (probesPendingAction.size() > 0) {
    DYSECTVERBOSE(true, "Handle timer actions");
    vector<Probe*>::iterator probeIter = probesPendingAction.begin();
    for(;probeIter != probesPendingAction.end(); probeIter++) {
      Probe* probe = *probeIter;
      Domain* dom = probe->getDomain();

      DYSECTVERBOSE(true, "Sending enqueued actions for timed probe: %x", dom->getId());
      probe->sendEnqueuedActions();

      if(probe->numWaitingProcs() > 0) {
        ProcessSet::ptr lprocset = probe->getWaitingProcs();
        probe->enableChildren(lprocset);
        if(probe->getLifeSpan() == fireOnce)
          probe->disable(lprocset);
        lprocset->continueProcs();
        probe->releaseWaitingProcs();
      }
    }
    probesPendingAction.clear();
  }
  pthread_mutex_unlock(&probesPendingActionMutex);
  return OK;
}
Example #2
0
Process::cb_ret_t Backend::handleTimeEvent() {
  // Get all subscribed events
  set<Event*>& events = Time::getTimeSubscribers();

  set<Event*>::iterator eventIter = events.begin();
  for(;eventIter != events.end(); eventIter++) {
    Event* event = *eventIter;
    ProcessSet::ptr procset = ((Time *)event)->getProcset();
    ProcessSet::iterator procIter = procset->begin();
    if(procset->size() == 0)
      continue;
    if(!event || !event->isEnabled(*procIter))
      continue; // this is to avoid a race condition where a time event occurs in the middle of iterating through the processes
    DYSECTVERBOSE(true, "Time event with timeout %d detected on %d processes", ((Time *)event)->getTimeout(), procset->size());
    for(;procIter != procset->end(); procIter++) {
      Process::ptr procPtr = *procIter;
      if(event && event->isEnabled(procPtr)) {
        Thread::ptr threadPtr = procPtr->threads().getInitialThread();
        Walker *proc = (Walker *)procPtr->getData();
        handleEvent(procPtr, threadPtr, event);
      }
    }
    if(event->getOwner()->getLifeSpan() == fireOnce)
      event->disable();
  }

  return Process::cbDefault;
}
Example #3
0
bool Probe::staticGroupWaiting() {
  assert(dom != 0);

  ProcessSet::ptr procset;
  dom->getAttached(procset);

  DYSECTVERBOSE(true, "staticGroupWaiting %d %d", procset->size(), waitingProcs->size());
  return (procset->size() <= waitingProcs->size());
}
Example #4
0
// XXX: Process scope for signal handlers
bool Async::enable(ProcessSet::ptr lprocset) {
  if(procset) {
    ProcessSet::ptr origSet = procset;

    procset = origSet->set_union(lprocset);  
  } else {
    procset = lprocset;
  }

  return enable();
}
Example #5
0
bool Location::disable(ProcessSet::ptr lprocset) {
  assert(owner != 0);
 
  if(codeLocations.empty()) {
    return Err::verbose(true, "No code locations");

  }

  if(!lprocset) {
    return Err::warn(false, "Process set not present");
  }

  ProcessSet::iterator procIter = lprocset->begin();
  for(;procIter != lprocset->end(); procIter++) {
    Process::ptr procPtr = *procIter;

    Walker* proc = (Walker*)procPtr->getData();

    vector<DysectAPI::CodeLocation*>::iterator locationIter = codeLocations.begin();
    for(;locationIter != codeLocations.end(); locationIter++) {
      DysectAPI::CodeLocation* location = *locationIter;

      if(!location->addProcLib(proc)) {
        return Err::warn(false, "Symbol not found in process");
      }

      vector<Dyninst::Address> addrs;
      
      if(!location->getAddrs(proc, addrs) || addrs.empty()) {
        return Err::warn(false, "Addresses for symbol could not be determined");
      }

      // Breakpoint locations at hand
      for(int i = 0; i < addrs.size() ; i++) {
        Dyninst::Address addr = addrs[i];
        
        if(!procPtr->rmBreakpoint(addr, bp)) {
          Err::verbose(false, "Breakpoint not removed! %s", ProcControlAPI::getLastErrorMsg());
        }
      }
    }
  }

  return true;
}
Example #6
0
ProcessSet::ptr ProcessMgr::filterDetached(ProcessSet::ptr inSet) {
  if(!inSet) {
    return inSet;
  }

  if(!detached) {
    return inSet;
  }

  return inSet->set_difference(detached);
}
Example #7
0
DysectAPI::DysectErrorCode Backend::resumeApplication() {
  ProcessSet::ptr allProcs = ProcessMgr::getAllProcs();

  if(!allProcs) {
    return Err::warn(Error, "Procset not available");
  }

  // Processes might have exited before setup
  allProcs = ProcessMgr::filterExited(allProcs);

  if(!allProcs) 
    return OK;

  if(allProcs->empty())
    return OK;

  if(allProcs->continueProcs()) {
    return OK;
  } else {
    return Err::warn(Error, "Procset could not continue processes");
  }
}
Example #8
0
ProcessSet::ptr ProcessMgr::filterExited(ProcessSet::ptr inSet) { 
  if(!inSet)
    return inSet;

  if(inSet->empty())
    return inSet;

  ProcessSet::ptr procs = ProcessSet::newProcessSet();
  // Filter out exited processes
  ProcessSet::iterator procIter = inSet->begin();
  for(; procIter != inSet->end(); procIter++) {
    Process::ptr process = *procIter;

    if(process->isTerminated() || process->isExited() || process->isCrashed() || process->isDetached()) {
      continue;
    }

    procs->insert(process);
  }
  
  return procs;
}
Example #9
0
bool ProcessMgr::detachAll() {
  
  Err::verbose(true, "Detaching from all!");

  if(!allProcs)
    return true;

  if(allProcs->size() <= 0)
    return true;

  Err::verbose(true, "Filtering set!");
  allProcs = filterExited(allProcs);

  if(!allProcs)
    return true;

  if(allProcs->size() <= 0)
    return true;

  Err::verbose(true, "Get running set!");
  // Continue stopped processes
  ProcessSet::ptr runningProcs = allProcs->getAnyThreadRunningSubset();
 
  if(runningProcs && (runningProcs->size() > 0)) {
    Err::verbose(true, "Stopping %d processes...", runningProcs->size());
    runningProcs->stopProcs();
    Err::verbose(true, "Processes stop done");
  }

  if(allProcs && allProcs->size() > 0) {
    Err::verbose(true, "Detaching from %d processes...", allProcs->size());
    allProcs->temporaryDetach();
  }

  Err::verbose(true, "Done");

  return true;
}
Example #10
0
DysectAPI::DysectErrorCode Backend::pauseApplication() {
  ProcessSet::ptr allProcs = ProcessMgr::getAllProcs();

  if(!allProcs) {
    return DYSECTWARN(Error, "Procset not available");
  }

  // Processes might have exited before setup
  allProcs = ProcessMgr::filterExited(allProcs);

  if(!allProcs)
    return OK;

  if(allProcs->empty())
    return OK;

  if(allProcs->stopProcs()) {
    DYSECTLOG(true, "stop all processes");
    return OK;
  } else {
    return DYSECTWARN(Error, "Procset could not stop processes");
  }
}
Example #11
0
bool ProcessMgr::detach(ProcessSet::ptr detachedSet) {
  if(!detachedSet) {
    return Err::warn(false, "detach from empty detachSet");
  }

  bool ret = detachedSet->temporaryDetach();
  if (ret == false) {
    return Err::warn(false, "detach from detachSet failed: %s", ProcControlAPI::getLastErrorMsg());
  }

  allProcs = allProcs->set_difference(detachedSet);
  detached = detached->set_union(detachedSet);

  return true;
}
Example #12
0
bool Probe::enable(ProcessSet::ptr procset) {
  assert(event != 0);
  assert(dom != 0);

  if(!dom->anyTargetsAttached())
    return true;

  ProcessSet::ptr staticProcs;
  if(!dom->getAttached(staticProcs)) {
    return DYSECTWARN(false, "Could not get static process set");
  }

  ProcessSet::ptr affectedProcs = staticProcs->set_intersection(procset);

  if(affectedProcs->size() <= 0) {
    return DYSECTVERBOSE(true, "No processes from incoming set attached for probe %lx, staticProcs %d procset %d", dom->getId(), staticProcs->size(), procset->size());
  }

  DYSECTVERBOSE(true, "Enabling probe %lx with dynamic set with %d processes", dom->getId(), affectedProcs->size());

  bool result = event->enable(affectedProcs);

  return result;
}
Example #13
0
bool Location::enable(ProcessSet::ptr lprocset) {
  assert(owner != 0);
 
  if(codeLocations.empty()) {
    return Err::verbose(true, "No code locations");

  }

  if(!lprocset) {
    return Err::warn(false, "Process set not present");
  }
  
  ProcessSet::iterator procIter = lprocset->begin();

  AddressSet::ptr addrset = AddressSet::newAddressSet();

  if(lprocset->size() <= 0) {
    return Err::info(true, "Process set empty!");
  }

  // Find library location for target processes
  for(;procIter != lprocset->end(); procIter++) {
    Process::ptr procPtr = *procIter;

    Walker* proc = (Walker*)procPtr->getData();

    vector<DysectAPI::CodeLocation*>::iterator locationIter = codeLocations.begin();
    for(;locationIter != codeLocations.end(); locationIter++) {
      DysectAPI::CodeLocation* location = *locationIter;

      if(!location->addProcLib(proc)) {
        return Err::warn(false, "Symbol not found in process");
      }

      vector<Dyninst::Address> addrs;
      
      if(!location->getAddrs(proc, addrs) || addrs.empty()) {
        return Err::warn(false, "Addresses for symbol could not be determined");
      }

      // Breakpoint locations at hand
      for(int i = 0; i < addrs.size() ; i++) {
        Dyninst::Address addr = addrs[i];
        
        if(!procPtr->addBreakpoint(addr, bp)) {
          return Err::verbose(false, "Breakpoint not installed: %s", ProcControlAPI::getLastErrorMsg());
        } else {
          Err::verbose(true, "Breakpoint installed at %lx", addr);
        }

        //addrset->insert(addr, procPtr);
      }

      //if(addrs.empty()) {
      //  Err::verbose(true, "No addresses");
      //}
    }

  }
  
  //if(addrset->size() <= 0) {
  //  return Err::verbose(true, "Empty address set");
  //}

  
  //if(!lprocset->addBreakpoint(addrset, nbp)) {
  //  return Err::warn(false, "Could not insert breakpoints!");
  //} else {
  //  Err::info(true, "%d breakpoints inserted in %d processes", addrset->size(), lprocset->size());
  //}

  return true;
}
Example #14
0
Process::cb_ret_t Backend::handleEvent(Dyninst::ProcControlAPI::Process::const_ptr curProcess,
                                 Dyninst::ProcControlAPI::Thread::const_ptr curThread,
                                 DysectAPI::Event* dysectEvent) {

  Process::cb_ret_t retState = Process::cbDefault;

  // Let event know that it was triggered.
  // Used for event composition
  Walker* proc = (Walker*)curProcess->getData();

  if(!proc) {
    DYSECTWARN(true, "Missing payload in process object: could not get walker for PID %d", curProcess->getPid());
  } else {
    dysectEvent->triggered(curProcess, curThread);

    // Find owning probe
    Probe* probe = dysectEvent->getOwner();


    if(!probe) {
      DYSECTWARN(true, "Probe could not be found for event object");
    } else {
      // If enqueued disabled - stop and await
      //if(probe->isDisabled(curProcess)) {
      //  probe->addWaitingProc(curProcess);

      //  return Process::cbProcStop;
      //  //return Process::cbDefault;
      //}

      // Composed events might require several events being triggered
      if(probe->wasTriggered(curProcess, curThread)) {
        // Required events indeed triggered
        // Evaluate conditions
        ConditionResult result;

        DYSECTVERBOSE(true, "Evaluate condition for %d!", curProcess->getPid());
        if(probe->evaluateConditions(result, curProcess, curThread) == DysectAPI::OK) {

          if(result == ResolvedTrue) {
            DYSECTVERBOSE(true, "Condition satisfied");

            Domain* dom = probe->getDomain();
            assert(dom != 0);

            if(dom->getWaitTime() == Wait::inf) {

              // Block strictly, until all processes have shown up
              DYSECTVERBOSE(true, "Enqueuing notification for static domain");
              probe->enqueueNotifyPacket();
              probe->enqueueAction(curProcess, curThread);

            } else if(dom->getWaitTime() != Wait::NoWait) {
              if(!DysectAPI::SafeTimer::syncTimerRunning(probe)) {
                DYSECTVERBOSE(true, "Start timer (%ld) and enqueue: %x", dom->getWaitTime(), dom->getId());
                DysectAPI::SafeTimer::startSyncTimer(probe);
              } else {
                DYSECTVERBOSE(true, "Timer already running - just enqueue");
              }

              if(probe->doNotify()) {
                probe->enqueueNotifyPacket();
              }

              probe->enqueueAction(curProcess, curThread);

            } else { // No-wait probe

              if(probe->doNotify()) {
                probe->notifyTriggered();
              }

              probe->triggerAction(curProcess, curThread);

            }
            ProcessSet::ptr lprocset;
            probe->getDomain()->getAttached(lprocset);

            if(probe->waitForOthers()) {
              DYSECTVERBOSE(true, "Wait (%ld) for group members %d/%d", dom->getWaitTime(), probe->getProcessCount(), lprocset->size());
              probe->addWaitingProc(curProcess);

              if((dom->getWaitTime() == Wait::inf) && (probe->staticGroupWaiting())) {
                DYSECTVERBOSE(true, "Sending enqueued notifications");

                if(probe->doNotify()) {
                  probe->sendEnqueuedNotifications();
                  pthread_mutex_lock(&probesPendingActionMutex);
                  probesPendingAction.push_back(probe);
                  pthread_mutex_unlock(&probesPendingActionMutex);
                }

                if (Backend::getPendingExternalAction == 0)
                    probe->sendEnqueuedActions();
              }

              retState = Process::cbThreadStop;

            } else {
              DYSECTVERBOSE(true, "Enable children for probe %x", dom->getId());
              probe->enqueueEnable(curProcess);

              probe->addWaitingProc(curProcess);
              retState = Process::cbProcStop;

              if(probe->getLifeSpan() == fireOnce) {
                DYSECTVERBOSE(true, "Requesting disablement of probe");
                probe->enqueueDisable(curProcess);
                retState = Process::cbProcStop;
              }
            }

            if(probe->waitForOthers() && (probe->getProcessCount() >= lprocset->size())) {
              DYSECTVERBOSE(true, "%d/%d group members reported, triggering action", probe->getProcessCount(), lprocset->size());
              if (!DysectAPI::SafeTimer::resetSyncTimer(probe)) {
                DYSECTWARN(false, "Failed to reset timer (%ld) and invoke: %x", dom->getWaitTime(), dom->getId());
              }
            }
#if 0
          } else if(result == CollectiveResolvable) {
            // Block process and await resolution of collective operations

            //probe->addWaitingCond(curProcess, curThread);
            Err::warn(false, "Condition stalls not yet supported");

            Err::verbose(true, "Stopping thread in process %d", curProcess->getPid());
            retState = Process::cbProcStop;

            //retState = Process::cbThreadStop;
#endif
          } else if(result == ResolvedFalse) {
              if(probe->getLifeSpan() == fireOnce) {
                DYSECTVERBOSE(true, "Requesting disablement of unresolved probe");
                // Get out of the way
                probe->enqueueDisable(curProcess);
                retState = Process::cbProcStop;

              } else {

                retState = Process::cbProcContinue;
              }

          }

        } else {
          DYSECTWARN(false, "Could not evaluate conditions for probe");
        }
      } else {
        retState = Process::cbProcContinue;
      }

    }
  }

  return retState;
}
Example #15
0
bool Probe::processRequests() {
  if(requestQueue.empty()) {
    return true;
  }

  pthread_mutex_lock(&requestQueueMutex); 
  vector<ProbeRequest*> queue = requestQueue;
  requestQueue.clear();
  pthread_mutex_unlock(&requestQueueMutex); 

  ProcessSet::ptr continueSet = ProcessSet::newProcessSet();
 
  // Sort queue

  deque<ProbeRequest*> sortedQueue;
  vector<ProbeRequest*>::iterator requestIter = queue.begin();
  for(int i = 0; requestIter != queue.end(); requestIter++) {
    ProbeRequest* request = *requestIter;

    if(!request) {
      DYSECTWARN(true, "Invalid request in request queue");
      break;
    }

    if(request->type == DisableType) {
      sortedQueue.push_back(request);
    } else {
      sortedQueue.push_front(request);
    }
  }

  if (sortedQueue.size() == 0)
    return true;

  DYSECTVERBOSE(true, "Handling %d process requests", sortedQueue.size());

  deque<ProbeRequest*>::iterator sortedRequestIter = sortedQueue.begin();
  for(int i = 0; sortedRequestIter != sortedQueue.end(); sortedRequestIter++) {
    ProbeRequest* request = *sortedRequestIter;

    if(!request) {
      DYSECTWARN(true, "Invalid request in request queue");
      break;
    }

    DYSECTVERBOSE(true, "processRequests() %d", i++);

    Probe* probe = request->probe;
    if(!probe) {
      DYSECTWARN(false, "Probe not found for disable request!");
      break;
    }

    ProcessSet::ptr waitingProcs = request->scope;
    if(waitingProcs && waitingProcs->size() > 0) {
      DYSECTVERBOSE(true, "Adding %d request processes to %d continue set...", waitingProcs->size(), continueSet->size());
      continueSet = continueSet->set_union(waitingProcs);
    }

    ProcessSet::ptr operationSet = ProcessSet::newProcessSet();
    ProcessSet::ptr stopSet = ProcessSet::newProcessSet();

    ProcessSet::ptr scope = request->scope;
    if(scope && scope->size() > 0) {
      DYSECTVERBOSE(true, "Adding processes from scope set (%d) to affected procs (%d)", scope->size(), operationSet->size());
      operationSet = operationSet->set_union(scope);
    }

    //
    // Filter out detached
    //
    operationSet = ProcessMgr::filterDetached(operationSet);
    stopSet = ProcessMgr::filterDetached(stopSet);
    DYSECTVERBOSE(true, "%d procs in op set, %d procs in stop set", operationSet->size(), stopSet->size());

    //
    // Stop processes
    //
  
    stopSet = operationSet->getAnyThreadRunningSubset();
    if(stopSet && stopSet->size() > 0) {
      DYSECTVERBOSE(true, "Stopping %d processes", stopSet->size());
      
      stopSet->stopProcs();
    }

    //
    // Carry out operations
    //

    if(operationSet && operationSet->size() > 0) {
      if(request->type == DisableType) {
        DYSECTVERBOSE(true, "Disabling %d processes", operationSet->size());
        probe->disable(operationSet);
      } else {
        DYSECTVERBOSE(true, "Enabling %d processes", operationSet->size());
        probe->enableChildren(operationSet);
      }
    }
    
    //
    // Processes must be started when all operations have been carried out.
    //
    if(operationSet && operationSet->size() > 0) {
      continueSet = continueSet->set_union(operationSet);
    }

    delete(request);
  }

  continueSet = ProcessMgr::filterDetached(continueSet);

  if(continueSet && continueSet->size() > 0) {
    DYSECTVERBOSE(true, "Continuing %d processes", continueSet->size());
    if(continueSet->size() == 1) {
      ProcessSet::iterator procIter = continueSet->begin();
      Process::ptr process = *procIter;
      DYSECTVERBOSE(true, "Continuing process %d", process->getPid());
    }
    
    continueSet->continueProcs();
  }

  DYSECTVERBOSE(true, "Done handling requests");

  return true;
}