text: """
  CPAchecker is a tool for configurable software verification.
  This file is part of CPAchecker.
  
  Copyright (C) 2007-2014  Dirk Beyer
  All rights reserved.
  
  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at
  
      http://www.apache.org/licenses/LICENSE-2.0
  
  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
  
  
  CPAchecker web page:
    http://cpachecker.sosy-lab.org
  """
  
  # prepare for Python 3
  from __future__ import absolute_import, print_function, unicode_literals
  
  import sys
  sys.dont_write_bytecode = True # prevent creation of .pyc files
  
  try:
    import Queue
  except ImportError: # Queue was renamed to queue in Python 3
    import queue as Queue
  
  import logging
  import os
  import resource
  import threading
  import time
  
  from .benchmarkDataStructures import CORELIMIT, MEMLIMIT, TIMELIMIT, SOFTTIMELIMIT
  from .runexecutor import RunExecutor
  from . import util as Util
  
  
  WORKER_THREADS = []
  STOPPED_BY_INTERRUPT = False
  
  _BYTE_FACTOR = 1000 # byte in kilobyte
  
  
  def executeBenchmarkLocaly(benchmark, outputHandler):
  
      runSetsExecuted = 0
  
      logging.debug("I will use {0} threads.".format(benchmark.numOfThreads))
  
      # iterate over run sets
      for runSet in benchmark.runSets:
  
          if STOPPED_BY_INTERRUPT: break
  
          (mod, rest) = benchmark.config.moduloAndRest
  
          if not runSet.shouldBeExecuted() \
                  or (runSet.index % mod != rest):
              outputHandler.outputForSkippingRunSet(runSet)
  
          elif not runSet.runs:
              outputHandler.outputForSkippingRunSet(runSet, "because it has no files")
  
          else:
              runSetsExecuted += 1
              # get times before runSet
              ruBefore = resource.getrusage(resource.RUSAGE_CHILDREN)
              wallTimeBefore = time.time()
              energyBefore = Util.getEnergy()
  
              outputHandler.outputBeforeRunSet(runSet)
  
              # put all runs into a queue
              for run in runSet.runs:
                  _Worker.workingQueue.put(run)
  
              # create some workers
              for i in range(benchmark.numOfThreads):
                  WORKER_THREADS.append(_Worker(i, outputHandler))
  
              # wait until all tasks are done,
              # instead of queue.join(), we use a loop and sleep(1) to handle KeyboardInterrupt
              finished = False
              while not finished and not STOPPED_BY_INTERRUPT:
                  try:
                      _Worker.workingQueue.all_tasks_done.acquire()
                      finished = (_Worker.workingQueue.unfinished_tasks == 0)
                  finally:
                      _Worker.workingQueue.all_tasks_done.release()
  
                  try:
                      time.sleep(0.1) # sleep some time
                  except KeyboardInterrupt:
                      killScriptLocal()
  
              # get times after runSet
              wallTimeAfter = time.time()
              energy = Util.getEnergy(energyBefore)
              usedWallTime = wallTimeAfter - wallTimeBefore
              ruAfter = resource.getrusage(resource.RUSAGE_CHILDREN)
              usedCpuTime = (ruAfter.ru_utime + ruAfter.ru_stime) \
                          - (ruBefore.ru_utime + ruBefore.ru_stime)
  
              if STOPPED_BY_INTERRUPT:
                  outputHandler.setError('interrupted')
              outputHandler.outputAfterRunSet(runSet, cpuTime=usedCpuTime, wallTime=usedWallTime, energy=energy)
  
      outputHandler.outputAfterBenchmark(STOPPED_BY_INTERRUPT)
  
  
  def killScriptLocal():
      global STOPPED_BY_INTERRUPT
      STOPPED_BY_INTERRUPT = True
  
      # kill running jobs
      Util.printOut("killing subprocesses...")
      for worker in WORKER_THREADS:
          worker.stop()
  
      # wait until all threads are stopped
      for worker in WORKER_THREADS:
          worker.join()
  
  
  class _Worker(threading.Thread):
      """
      A Worker is a deamonic thread, that takes jobs from the workingQueue and runs them.
      """
      workingQueue = Queue.Queue()
  
      def __init__(self, number, outputHandler):
          threading.Thread.__init__(self) # constuctor of superclass
          self.numberOfThread = number
          self.outputHandler = outputHandler
          self.runExecutor = RunExecutor()
          self.setDaemon(True)
          self.start()
  
      def run(self):
          while not _Worker.workingQueue.empty() and not STOPPED_BY_INTERRUPT:
              currentRun = _Worker.workingQueue.get_nowait()
              try:
                  self.execute(currentRun)
              except BaseException as e:
                  logging.exception('Exception during run execution')
              _Worker.workingQueue.task_done()
  
  
      def execute(self, run):
          """
          This function executes the tool with a sourcefile with options.
          It also calls functions for output before and after the run.
          """
          self.outputHandler.outputBeforeRun(run)
          benchmark = run.runSet.benchmark
  
          # calculate cores to use
          myCpus = None
          if CORELIMIT in benchmark.rlimits:
              allCpus = self.runExecutor.cpus
              if not allCpus:
                  sys.exit("Cannot limit number of CPU cores because cgroups are not available.")
              myCpuCount = benchmark.rlimits[CORELIMIT]
              totalCpuCount = len(allCpus)
              if myCpuCount > totalCpuCount:
                  sys.exit("Cannot execute runs on {0} CPU cores, only {1} are available.".format(myCpuCount, totalCpuCount))
              myCpusStart = (self.numberOfThread * myCpuCount) % totalCpuCount
              myCpusEnd = (myCpusStart + myCpuCount - 1) % totalCpuCount
              myCpus = map(lambda i: allCpus[i], range(myCpusStart, myCpusEnd + 1))
  
          memlimit = None
          if MEMLIMIT in benchmark.rlimits:
              memlimit = benchmark.rlimits[MEMLIMIT] * _BYTE_FACTOR * _BYTE_FACTOR # MB to Byte
  
          maxLogfileSize = benchmark.config.maxLogfileSize
          if maxLogfileSize:
              maxLogfileSize *= _BYTE_FACTOR * _BYTE_FACTOR # MB to Byte
          elif maxLogfileSize == -1:
              maxLogfileSize = None
  
          (run.wallTime, run.cpuTime, memUsage, returnvalue, terminationReason, energy) = \
              self.runExecutor.executeRun(
                  run.getCmdline(), run.logFile,
                  hardtimelimit=benchmark.rlimits.get(TIMELIMIT),
                  softtimelimit=benchmark.rlimits.get(SOFTTIMELIMIT),
                  myCpus=myCpus,
                  memlimit=memlimit,
                  environments=benchmark.getEnvironments(),
                  workingDir=benchmark.workingDirectory(),
                  maxLogfileSize=maxLogfileSize)
          run.values['memUsage'] = memUsage
          run.values['energy'] = energy
  
          if self.runExecutor.PROCESS_KILLED:
              # If the run was interrupted, we ignore the result and cleanup.
              run.wallTime = 0
              run.cpuTime = 0
              try:
                  if benchmark.config.debug:
                     os.rename(run.logFile, run.logFile + ".killed")
                  else:
                     os.remove(run.logFile)
              except OSError:
                  pass
              return
  
          run.afterExecution(returnvalue)
          self.outputHandler.outputAfterRun(run)
  
  
      def stop(self):
          # asynchronous call to runexecutor,
          # the worker will stop asap, but not within this method.
          self.runExecutor.kill()
  