-
Notifications
You must be signed in to change notification settings - Fork 2
/
ExitCodes.py
104 lines (96 loc) · 3.87 KB
/
ExitCodes.py
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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
"""Create textual descriptions of exit statuses."""
__author__ = "David McClosky (dmcc AT cs.brown.edu)"
import os, signal
def signum_to_name(signum):
for obj in dir(signal):
if obj.startswith('SIG') and signum == getattr(signal, obj):
return obj
else:
return None
class ExitCode(Exception):
"""Represents the exit code of a spawned command."""
def __init__(self, exitcode, message=''):
"""exitcode is the exit status of a command, message is a
description which will be prepended in the str() of this."""
self.exitcode = exitcode
self.message = message
self.exitstatus = None
self.exited = None
self.killedbysignalnum = None
self.killedbysignal = None
self.stoppedbysignalnum = None
self.stoppedbysignal = None
self.coredumped = os.WCOREDUMP(exitcode)
if os.WIFEXITED(exitcode):
self.exited = True
self.exitstatus = os.WEXITSTATUS(exitcode)
if os.WIFSIGNALED(exitcode):
self.killedbysignalnum = os.WTERMSIG(exitcode)
self.killedbysignal = signum_to_name(self.killedbysignalnum)
if os.WIFSTOPPED(exitcode):
self.stoppedbysignalnum = os.WSTOPSIG(self.exitcode)
self.stoppedbysignal = signum_to_name(self.stoppedbysignalnum)
def describe(self, exitcodedescs=None):
desc = []
if self.killedbysignalnum:
if self.killedbysignal:
signame = " (%s)" % self.killedbysignal
else:
signame = ""
desc.append("Killed by signal %d%s" % (self.killedbysignalnum,
signame))
if self.exited:
if exitcodedescs and exitcodedescs.get(self.exitcode):
codedesc = " (%s)" % exitcodedescs.get(self.exitcode)
else:
codedesc = ''
desc.append("Exited with code %d%s" % (self.exitcode, codedesc))
if self.stoppedbysignalnum:
if self.stoppedbysignal:
signame = " (%s)" % self.stoppedbysignal
else:
signame = ""
desc.append("Stopped by signal %d%s" % (self.stoppedbysignalnum,
signame))
if self.coredumped:
desc.append("coredumped")
return ', '.join(desc)
def __repr__(self):
return "<{}: {}, message={!r}>".format(self.__class__.__name__,
self.exitcode,
self.message)
def __str__(self):
return "%s%s (exit status %s)" % \
(self.message, self.describe(), self.exitcode)
# DEPRECATED
def describe_exit_status(exitstatus, exitcodedescs=None):
import warnings
warnings.warn("Use ExitCode instead of describe_exit_status()",
DeprecationWarning)
desc = []
if os.WIFSIGNALED(exitstatus):
signum = os.WTERMSIG(exitstatus)
signame = signum_to_name(signum)
if signame:
signame = " (%s)" % signame
else:
signame = ""
desc.append("Killed by signal %d%s" % (signum, signame))
if os.WIFEXITED(exitstatus):
exitcode = os.WEXITSTATUS(exitstatus)
if exitcodedescs and exitcodedescs.get(exitcode):
codedesc = " (%s)" % exitcodedescs.get(exitcode)
else:
codedesc = ''
desc.append("Exited with code %d%s" % (exitcode, codedesc))
if os.WIFSTOPPED(exitstatus):
desc.append("Stopped by signal %d" % os.WSTOPSIG(exitstatus))
if os.WCOREDUMP(exitstatus):
desc.append("coredumped")
return desc
# a shorter version
describe = describe_exit_status
if __name__ == "__main__":
import sys
for status in sys.argv[1:]:
print((status, describe_exit_status(int(status)), ExitCode(int(status))))