aboutsummaryrefslogtreecommitdiffstats
path: root/experiment/executable/executable.py
blob: 897c2d90151f7da1a92b6faecc7e43f05a033e7e (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
import sys
import subprocess
import signal
from ..litmus_util import is_executable

class Executable(object):
    """Parent object that represents an executable for use in task-sets."""

    def __init__(self, exec_file, extra_args=None, stdout_file = None, stderr_file = None):
        self.exec_file = exec_file
        self.cwd = None
        self.stdout_file = stdout_file
        self.stderr_file = stderr_file
        self.sp = None

        if extra_args is None:
            self.extra_args = None
        else:
            self.extra_args = list(extra_args) # make a duplicate

        if not is_executable(self.exec_file):
            raise Exception("Not executable ? : %s" % self.exec_file)

    def __del__(self):
        # Try and clean up
        if self.stdout_file is not None:
            self.stdout_file.close()
        if self.stderr_file is not None:
            self.stderr_file.close()

        if self.sp is not None:
            try:
                self.sp.terminate()
            except OSError as e:
                if e.errno == 3:
                    pass # no such process (already killed), okay
                else:
                    raise e

    def __get_full_command(self):
        full_command = [self.exec_file]
        if self.extra_args is not None:
            full_command += self.extra_args
        return full_command

    def __str__(self):
        return " ".join(self.__get_full_command())

    def execute(self):
        """Execute the binary."""
        full_command = self.__get_full_command()
        self.sp = subprocess.Popen(full_command, stdout=self.stdout_file,
                stderr=self.stderr_file, cwd=self.cwd)

    def kill(self):
        self.sp.kill()

    def interrupt(self):
        self.sp.send_signal(signal.SIGINT)

    def terminate(self):
        """Send the terminate signal to the binary."""
        self.sp.terminate()

    def wait(self):
        """Wait until the executable is finished, checking return code.

        If the exit status is non-zero, raise an exception.

        """

        self.sp.wait()
        if self.sp.returncode != 0:
            print >>sys.stderr, "Non-zero return: %s %s" % (self.exec_file, self.extra_args)