diff options
| author | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-04-12 11:30:27 -0400 |
|---|---|---|
| committer | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-04-12 11:30:27 -0400 |
| commit | 09bc409657606a37346d82ab1e4c44a165bd3541 (patch) | |
| tree | 72c569f69f37acafdc89fde4724bde7b373ef8f9 | |
| parent | 384e322f974534c1c734db144633e3c3e002b1f8 (diff) | |
Improved error handling in run_exps.py.
| -rw-r--r-- | common.py | 6 | ||||
| -rw-r--r-- | parse/sched.py | 1 | ||||
| -rw-r--r-- | run/executable/executable.py | 6 | ||||
| -rw-r--r-- | run/experiment.py | 128 | ||||
| -rw-r--r-- | run/litmus_util.py | 23 | ||||
| -rwxr-xr-x | run_exps.py | 18 |
6 files changed, 114 insertions, 68 deletions
| @@ -26,15 +26,17 @@ def get_executable_hint(prog, hint, optional=False): | |||
| 26 | '''Search for @prog in system PATH. Print @hint if no binary is found. | 26 | '''Search for @prog in system PATH. Print @hint if no binary is found. |
| 27 | Die if not @optional.''' | 27 | Die if not @optional.''' |
| 28 | try: | 28 | try: |
| 29 | prog = get_executable(prog) | 29 | full_path = get_executable(prog) |
| 30 | except IOError: | 30 | except IOError: |
| 31 | if not optional: | 31 | if not optional: |
| 32 | sys.stderr.write(("Cannot find executable '%s' in PATH. This is " +\ | 32 | sys.stderr.write(("Cannot find executable '%s' in PATH. This is " +\ |
| 33 | "a part of '%s' which should be added to PATH.\n")\ | 33 | "a part of '%s' which should be added to PATH.\n")\ |
| 34 | % (prog, hint)) | 34 | % (prog, hint)) |
| 35 | sys.exit(1) | 35 | sys.exit(1) |
| 36 | else: | ||
| 37 | full_path = None | ||
| 36 | 38 | ||
| 37 | return prog | 39 | return full_path |
| 38 | 40 | ||
| 39 | def get_config_option(option): | 41 | def get_config_option(option): |
| 40 | '''Search for @option in installed kernel config (if present). | 42 | '''Search for @option in installed kernel config (if present). |
diff --git a/parse/sched.py b/parse/sched.py index 2da0149..147a2e5 100644 --- a/parse/sched.py +++ b/parse/sched.py | |||
| @@ -161,6 +161,7 @@ def extract_sched_data(result, data_dir, work_dir): | |||
| 161 | cmd_arr = [conf.BINS['st_show']] | 161 | cmd_arr = [conf.BINS['st_show']] |
| 162 | cmd_arr.extend(bins) | 162 | cmd_arr.extend(bins) |
| 163 | with open(output_file, "w") as f: | 163 | with open(output_file, "w") as f: |
| 164 | print("calling %s" % cmd_arr) | ||
| 164 | subprocess.call(cmd_arr, cwd=data_dir, stdout=f) | 165 | subprocess.call(cmd_arr, cwd=data_dir, stdout=f) |
| 165 | 166 | ||
| 166 | task_dict = defaultdict(lambda : | 167 | task_dict = defaultdict(lambda : |
diff --git a/run/executable/executable.py b/run/executable/executable.py index 02e35ae..263e305 100644 --- a/run/executable/executable.py +++ b/run/executable/executable.py | |||
| @@ -1,13 +1,13 @@ | |||
| 1 | import sys | 1 | import sys |
| 2 | import subprocess | 2 | import subprocess |
| 3 | import signal | 3 | import signal |
| 4 | from common import is_executable | 4 | from common import get_executable |
| 5 | 5 | ||
| 6 | class Executable(object): | 6 | class Executable(object): |
| 7 | '''Parent object that represents an executable for use in task-sets.''' | 7 | '''Parent object that represents an executable for use in task-sets.''' |
| 8 | 8 | ||
| 9 | def __init__(self, exec_file, extra_args=None, stdout_file = None, stderr_file = None): | 9 | def __init__(self, exec_file, extra_args=None, stdout_file = None, stderr_file = None): |
| 10 | self.exec_file = exec_file | 10 | self.exec_file = get_executable(exec_file) |
| 11 | self.cwd = None | 11 | self.cwd = None |
| 12 | self.stdout_file = stdout_file | 12 | self.stdout_file = stdout_file |
| 13 | self.stderr_file = stderr_file | 13 | self.stderr_file = stderr_file |
| @@ -18,7 +18,7 @@ class Executable(object): | |||
| 18 | else: | 18 | else: |
| 19 | self.extra_args = [str(a) for a in list(extra_args)] # make a duplicate | 19 | self.extra_args = [str(a) for a in list(extra_args)] # make a duplicate |
| 20 | 20 | ||
| 21 | if not is_executable(self.exec_file): | 21 | if not self.exec_file: |
| 22 | raise Exception("Not executable ? : %s" % self.exec_file) | 22 | raise Exception("Not executable ? : %s" % self.exec_file) |
| 23 | 23 | ||
| 24 | def __del__(self): | 24 | def __del__(self): |
diff --git a/run/experiment.py b/run/experiment.py index e5811f8..ff0e9f3 100644 --- a/run/experiment.py +++ b/run/experiment.py | |||
| @@ -1,7 +1,9 @@ | |||
| 1 | import common as com | ||
| 1 | import os | 2 | import os |
| 2 | import time | 3 | import time |
| 3 | import run.litmus_util as lu | 4 | import run.litmus_util as lu |
| 4 | import shutil as sh | 5 | import shutil as sh |
| 6 | import traceback | ||
| 5 | from operator import methodcaller | 7 | from operator import methodcaller |
| 6 | 8 | ||
| 7 | class ExperimentException(Exception): | 9 | class ExperimentException(Exception): |
| @@ -15,17 +17,12 @@ class ExperimentDone(ExperimentException): | |||
| 15 | def __str__(self): | 17 | def __str__(self): |
| 16 | return "Experiment finished already: %d" % self.name | 18 | return "Experiment finished already: %d" % self.name |
| 17 | 19 | ||
| 18 | |||
| 19 | class ExperimentInterrupted(ExperimentException): | ||
| 20 | '''Raised when an experiment appears to be interrupted (partial results).''' | ||
| 21 | def __str__(self): | ||
| 22 | return "Experiment was interrupted in progress: %d" % self.name | ||
| 23 | |||
| 24 | |||
| 25 | class ExperimentFailed(ExperimentException): | 20 | class ExperimentFailed(ExperimentException): |
| 26 | def __str__(self): | 21 | def __str__(self): |
| 27 | return "Experiment failed during execution: %d" % self.name | 22 | return "Experiment failed during execution: %d" % self.name |
| 28 | 23 | ||
| 24 | class SystemCorrupted(Exception): | ||
| 25 | pass | ||
| 29 | 26 | ||
| 30 | class Experiment(object): | 27 | class Experiment(object): |
| 31 | '''Execute one task-set and save the results. Experiments have unique IDs.''' | 28 | '''Execute one task-set and save the results. Experiments have unique IDs.''' |
| @@ -44,6 +41,8 @@ class Experiment(object): | |||
| 44 | self.exec_out = None | 41 | self.exec_out = None |
| 45 | self.exec_err = None | 42 | self.exec_err = None |
| 46 | 43 | ||
| 44 | self.task_batch = com.num_cpus() | ||
| 45 | |||
| 47 | self.__make_dirs() | 46 | self.__make_dirs() |
| 48 | self.__assign_executable_cwds() | 47 | self.__assign_executable_cwds() |
| 49 | self.__setup_tracers(tracer_types) | 48 | self.__setup_tracers(tracer_types) |
| @@ -84,65 +83,67 @@ class Experiment(object): | |||
| 84 | executable.cwd = self.working_dir | 83 | executable.cwd = self.working_dir |
| 85 | map(assign_cwd, self.executables) | 84 | map(assign_cwd, self.executables) |
| 86 | 85 | ||
| 87 | def __run_tasks(self): | 86 | def __kill_all(self): |
| 88 | already_waiting = lu.waiting_tasks() | 87 | # Give time for whatever failed to finish failing |
| 88 | time.sleep(2) | ||
| 89 | |||
| 90 | released = lu.release_tasks() | ||
| 91 | self.log("Re-released %d tasks" % released) | ||
| 89 | 92 | ||
| 90 | if already_waiting: | 93 | time.sleep(5) |
| 91 | self.log("Already %d tasks waiting for release!") | ||
| 92 | self.log("Experiment will fail if any of these tasks are released.") | ||
| 93 | 94 | ||
| 94 | self.log("Starting the programs") | 95 | self.log("Killing all tasks") |
| 95 | for e in self.executables: | 96 | for e in self.executables: |
| 96 | try: | 97 | try: |
| 98 | e.kill() | ||
| 99 | except: | ||
| 100 | pass | ||
| 101 | |||
| 102 | time.sleep(2) | ||
| 103 | |||
| 104 | def __run_tasks(self): | ||
| 105 | self.log("Starting %d tasks" % len(self.executables)) | ||
| 106 | |||
| 107 | for i,e in enumerate(self.executables): | ||
| 108 | try: | ||
| 97 | e.execute() | 109 | e.execute() |
| 98 | except: | 110 | except: |
| 99 | raise Exception("Executable failed: %s" % e) | 111 | raise Exception("Executable failed: %s" % e) |
| 100 | 112 | ||
| 101 | self.log("Sleeping until tasks are ready for release...") | 113 | self.log("Sleeping until tasks are ready for release...") |
| 102 | start = time.clock() | 114 | start = time.time() |
| 103 | while (lu.waiting_tasks() - already_waiting) < len(self.executables): | 115 | while lu.waiting_tasks() < len(self.executables): |
| 104 | if time.clock() - start > 30.0: | 116 | if time.time() - start > 30.0: |
| 105 | raise Exception("Too much time has passed waiting for tasks!") | 117 | s = "waiting: %d, submitted: %d" %\ |
| 118 | (lu.waiting_tasks(), len(self.executables)) | ||
| 119 | raise Exception("Too much time spent waiting for tasks! %s" % s) | ||
| 106 | time.sleep(1) | 120 | time.sleep(1) |
| 107 | 121 | ||
| 108 | # Exact tracers (like overheads) must be started right after release or | 122 | # Exact tracers (like overheads) must be started right after release or |
| 109 | # measurements will be full of irrelevant records | 123 | # measurements will be full of irrelevant records |
| 110 | self.log("Starting %d released tracers" % len(self.exact_tracers)) | 124 | self.log("Starting %d released tracers" % len(self.exact_tracers)) |
| 111 | map(methodcaller('start_tracing'), self.exact_tracers) | 125 | map(methodcaller('start_tracing'), self.exact_tracers) |
| 126 | time.sleep(1) | ||
| 112 | 127 | ||
| 113 | self.log("Releasing %d tasks" % len(self.executables)) | 128 | try: |
| 114 | released = lu.release_tasks() | 129 | self.log("Releasing %d tasks" % len(self.executables)) |
| 115 | |||
| 116 | ret = True | ||
| 117 | if released != len(self.executables): | ||
| 118 | # Some tasks failed to release, kill all tasks and fail | ||
| 119 | # Need to re-release non-released tasks before we can kill them though | ||
| 120 | self.log("Failed to release {} tasks! Re-releasing and killing".format( | ||
| 121 | len(self.executables) - released, len(self.executables))) | ||
| 122 | time.sleep(5) | ||
| 123 | |||
| 124 | released = lu.release_tasks() | 130 | released = lu.release_tasks() |
| 125 | 131 | ||
| 126 | self.log("Re-released %d tasks" % released) | 132 | if released != len(self.executables): |
| 127 | 133 | # Some tasks failed to release, kill all tasks and fail | |
| 128 | time.sleep(5) | 134 | # Need to release non-released tasks before they can be killed |
