ATLAS Offline Software
Loading...
Searching...
No Matches
python.TrigValSteering.Step.Step Class Reference
Inheritance diagram for python.TrigValSteering.Step.Step:
Collaboration diagram for python.TrigValSteering.Step.Step:

Classes

class  OutputStream

Public Types

typedef HLT::TypeInformation::for_each_type_c< typenameEDMLIST::map, my_functor, my_result<>, my_arg< HLT::TypeInformation::get_cont, CONTAINER > >::type result

Public Member Functions

 __init__ (self, name=None)
 get_log_file_name (self)
 configure (self, test=None)
 report_result (self, result=None, name=None)
 misconfig_abort (self, error_msg, *args, **kwargs)
 run (self, dry_run=False)

Public Attributes

 log = get_logger()
 name = name
 type = None
 executable = None
str args = ''
 cmd_prefix = None
 cmd_suffix = None
 output_stream = self.OutputStream.FILE_ONLY
 log_file_name = None
bool auto_report_result = False
bool required = False
bool depends_on_previous = False
bool depends_on_exec = False
 timeout = None
bool prmon = False
int prmon_interval = 5
 workdir = None

Private Member Functions

 __trace_and_kill (self, pid, signal, backtrace_list)
 __execute_with_timeout (self, cmd, timeout_sec)
 __start_prmon (self)
 __stop_prmon (self, prmon_proc)

Detailed Description

Base class for a step of a Trigger ART test

Definition at line 22 of file Step.py.

Member Typedef Documentation

◆ result

Definition at line 90 of file EDM_MasterSearch.h.

Constructor & Destructor Documentation

◆ __init__()

python.TrigValSteering.Step.Step.__init__ ( self,
name = None )

Definition at line 31 of file Step.py.

31 def __init__(self, name=None):
32 self.log = get_logger()
33 self.name = name
34 self.type = None
35 self.executable = None
36 self.args = ''
37 self.cmd_prefix = None
38 self.cmd_suffix = None
39 self.output_stream = self.OutputStream.FILE_ONLY
40 self.log_file_name = None
41 self.result = None
42 self.auto_report_result = False
43 self.required = False
44 self.depends_on_previous = False # skip if previous step in the current step list failed
45 self.depends_on_exec = False # (only for CheckSteps) skip if ExecSteps failed
46 self.timeout = None
47 self.prmon = False
48 self.prmon_interval = 5 # monitoring interval in seconds
49 self.workdir = None
50

Member Function Documentation

◆ __execute_with_timeout()

python.TrigValSteering.Step.Step.__execute_with_timeout ( self,
cmd,
timeout_sec )
private
Execute a shell process and kill it if it doesn't finish
before timeout_sec seconds pass. The implementation is based on
https://stackoverflow.com/a/10012262 and https://stackoverflow.com/a/4791612
In addition, a backtrace is produced for the timed out process and its children.

Definition at line 114 of file Step.py.

114 def __execute_with_timeout(self, cmd, timeout_sec):
115 '''
116 Execute a shell process and kill it if it doesn't finish
117 before timeout_sec seconds pass. The implementation is based on
118 https://stackoverflow.com/a/10012262 and https://stackoverflow.com/a/4791612
119 In addition, a backtrace is produced for the timed out process and its children.
120 '''
121 proc = subprocess.Popen(cmd, shell=True, preexec_fn=os.setsid)
122 backtrace_list = ['']
123 timer = Timer(timeout_sec, self.__trace_and_kill,
124 [os.getpgid(proc.pid), signal.SIGKILL, backtrace_list])
125 try:
126 timer.start()
127 proc.communicate()
128 finally:
129 timer.cancel()
130
131 if proc.returncode == -signal.SIGKILL:
132 self.log.error('%s killed on timeout of %s seconds',
133 self.name, self.timeout)
134 if (self.output_stream == self.OutputStream.FILE_ONLY or
135 self.output_stream == self.OutputStream.FILE_AND_STDOUT):
136 with open(self.get_log_file_name(), 'a') as log_file:
137 log_file.write(
138 'ERROR process killed on timeout '
139 'of {} seconds, command was {}\n'.format(
140 self.timeout, cmd))
141 log_file.write(backtrace_list[0])
142 return signal.SIGKILL # return 9 instead of -9
143
144 return proc.returncode
145

◆ __start_prmon()

python.TrigValSteering.Step.Step.__start_prmon ( self)
private

Definition at line 146 of file Step.py.

146 def __start_prmon(self):
147 self.log.debug('Starting prmon for pid %d', os.getpid())
148 prmon_cmd = 'prmon --pid {:d} --interval {:d}'.format(os.getpid(), self.prmon_interval)
149 prmon_cmd +=' --filename prmon.{name:s}.txt --json-summary prmon.summary.{name:s}.json'.format(name=self.name)
150 prmon_cmd +=' --log-filename prmon.{name:s}.log'.format(name=self.name)
151 return subprocess.Popen(prmon_cmd, shell=True)
152
const bool debug

◆ __stop_prmon()

python.TrigValSteering.Step.Step.__stop_prmon ( self,
prmon_proc )
private

Definition at line 153 of file Step.py.

153 def __stop_prmon(self, prmon_proc):
154 self.log.debug('Stopping prmon')
155 try:
156 prmon_proc.send_signal(signal.SIGUSR1)
157 countWait = 0
158 while (not prmon_proc.poll()) and countWait < 10:
159 time.sleep(0.1)
160 countWait += 1
161 except OSError as err:
162 self.log.warning('Error while stopping prmon: %s', err)
163 pass
164

◆ __trace_and_kill()

python.TrigValSteering.Step.Step.__trace_and_kill ( self,
pid,
signal,
backtrace_list )
private
Produce a backtrace for a process and its children, then call
os.killpg on the process. The last argument is a list of strings
where the first is filled with the backtrace by this function
(it has to be a list to be mutable).

Definition at line 87 of file Step.py.

87 def __trace_and_kill(self, pid, signal, backtrace_list):
88 '''
89 Produce a backtrace for a process and its children, then call
90 os.killpg on the process. The last argument is a list of strings
91 where the first is filled with the backtrace by this function
92 (it has to be a list to be mutable).
93 '''
94 try:
95 # Produce backtrace for the parent and all children
96 import psutil
97 parent = psutil.Process(pid)
98 backtrace = ''
99 for proc in [parent] + parent.children(recursive=True):
100 backtrace += '\nTraceback for {} PID {}:\n'.format(proc.name(), proc.pid)
101 backtrace += subprocess.check_output('$ROOTSYS/etc/gdb-backtrace.sh {}'.format(proc.pid),
102 stderr=subprocess.STDOUT, shell=True).decode('utf-8')
103 backtrace_list[0] = backtrace
104
105 # Kill the process
106 os.killpg(pid, signal)
107
108 except Exception as e:
109 # This may happen e.g. if one of the processes finishes before we generate backtrace
110 msg = 'Caught exception while generating backtrace: ' + str(e)
111 backtrace_list[0] = msg
112 self.log.error(msg)
113

◆ configure()

python.TrigValSteering.Step.Step.configure ( self,
test = None )
Can be implemented by derived classes.
Base class implementation only prints the configuration to debug log.

Definition at line 54 of file Step.py.

54 def configure(self, test=None):
55 '''
56 Can be implemented by derived classes.
57 Base class implementation only prints the configuration to debug log.
58 '''
59 self.log.debug(
60 'Step configuration:\n-- %s\n',
61 '\n-- '.join(['{}: {}'.format(k, v) for k, v in self.__dict__.items()]))
62
bool configure(asg::AnaToolHandle< ITrigGlobalEfficiencyCorrectionTool > &tool, ToolHandleArray< IAsgElectronEfficiencyCorrectionTool > &electronEffToolsHandles, ToolHandleArray< IAsgElectronEfficiencyCorrectionTool > &electronSFToolsHandles, ToolHandleArray< CP::IMuonTriggerScaleFactors > &muonToolsHandles, ToolHandleArray< IAsgPhotonEfficiencyCorrectionTool > &photonEffToolsHandles, ToolHandleArray< IAsgPhotonEfficiencyCorrectionTool > &photonSFToolsHandles, const std::string &triggers, const std::map< std::string, std::string > &legsPerTool, unsigned long nToys, bool debug)

◆ get_log_file_name()

python.TrigValSteering.Step.Step.get_log_file_name ( self)

Definition at line 51 of file Step.py.

51 def get_log_file_name(self):
52 return self.log_file_name or self.name+'.log'
53

◆ misconfig_abort()

python.TrigValSteering.Step.Step.misconfig_abort ( self,
error_msg,
* args,
** kwargs )
Print an error message (arguments passed to logging.error),
report non-zero art-result and exit the process with non-zero code

Definition at line 78 of file Step.py.

78 def misconfig_abort(self, error_msg, *args, **kwargs):
79 '''
80 Print an error message (arguments passed to logging.error),
81 report non-zero art-result and exit the process with non-zero code
82 '''
83 self.log.error('Misconfiguration in %s: '+error_msg, self.name, *args, **kwargs)
84 self.report_result(1, 'TestConfig')
85 sys.exit(1)
86

◆ report_result()

python.TrigValSteering.Step.Step.report_result ( self,
result = None,
name = None )

Definition at line 63 of file Step.py.

63 def report_result(self, result=None, name=None):
64 if result is None:
65 if self.result is not None:
66 result = self.result
67 else:
68 self.misconfig_abort('report_result was called but result is None')
69
70 if name is None:
71 if self.name is not None:
72 name = self.name
73 else:
74 name = 'UnnamedStep'
75
76 art_result(result, name)
77

◆ run()

python.TrigValSteering.Step.Step.run ( self,
dry_run = False )

Definition at line 165 of file Step.py.

165 def run(self, dry_run=False):
166 cmd = '{} {}'.format(self.executable, self.args)
167 if self.cmd_prefix:
168 cmd = self.cmd_prefix + cmd
169 if self.cmd_suffix:
170 cmd += self.cmd_suffix
171 if self.output_stream == self.OutputStream.NO_PRINT:
172 cmd += ' >/dev/null 2>&1'
173 elif self.output_stream == self.OutputStream.FILE_ONLY:
174 cmd += ' >{} 2>&1'.format(self.get_log_file_name())
175 elif self.output_stream == self.OutputStream.FILE_AND_STDOUT:
176 cmd += ' 2>&1 | tee {}; exit ${{PIPESTATUS[0]}}'.format(self.get_log_file_name())
177 elif self.output_stream == self.OutputStream.STDOUT_ONLY:
178 cmd += ' 2>&1'
179
180 self.log.info('Running %s step using command:\n%s', self.name, cmd)
181 if dry_run:
182 self.result = 0
183 else:
184 with remember_cwd():
185 if self.workdir:
186 assert '..' not in self.workdir, "Illegal path for workdir -- must be a subdirectory of CWD"
187 assert not self.workdir.startswith('/'), "Illegal path for workdir -- no absolute paths!"
188 os.makedirs(self.workdir,exist_ok=True)
189 os.chdir(self.workdir)
190
191 if self.prmon:
192 prmon_proc = self.__start_prmon()
193 if self.timeout:
194 self.result = self.__execute_with_timeout(cmd, self.timeout)
195 else:
196 self.result = subprocess.call(cmd, shell=True)
197 if self.prmon:
198 self.__stop_prmon(prmon_proc)
199
200 if self.auto_report_result:
201 self.report_result()
202
203 # Print full log to stdout for failed steps if running in CI
204 if self.required \
205 and self.result != 0 \
206 and running_in_CI() \
207 and self.output_stream==self.OutputStream.FILE_ONLY:
208 self.log.error('Step failure while running in CI. Printing partial log %s', self.get_log_file_name())
209
210 # Common error patterns (might be good to use all patterns from check_log.py)
211 error_patterns = '^ERROR| ERROR | FATAL |[Tt]raceback'
212 grep_with_context(open(self.get_log_file_name()), error_patterns, lines=100)
213
214 # Print also sub-step logs for transforms
215 if self.executable.endswith('_tf.py'):
216 log = open(self.get_log_file_name()).read()
217 step_matches = re.findall('Logs for (.*) are in (.*)', log)
218 if not step_matches:
219 self.log.warning('Failed to determine sub-step log names, cannot print the full sub-step logs')
220 else:
221 step_log_names = [m[1] for m in step_matches]
222 for step_log_name in step_log_names:
223 if os.path.isfile(step_log_name):
224 self.log.info('Printing partial sub-step log file %s', step_log_name)
225 grep_with_context(open(step_log_name), error_patterns, lines=100)
226
227 return self.result, cmd
228
229
Definition run.py:1
IovVectorMap_t read(const Folder &theFolder, const SelectionCriterion &choice, const unsigned int limit=10)

Member Data Documentation

◆ args

str python.TrigValSteering.Step.Step.args = ''

Definition at line 36 of file Step.py.

◆ auto_report_result

bool python.TrigValSteering.Step.Step.auto_report_result = False

Definition at line 42 of file Step.py.

◆ cmd_prefix

python.TrigValSteering.Step.Step.cmd_prefix = None

Definition at line 37 of file Step.py.

◆ cmd_suffix

python.TrigValSteering.Step.Step.cmd_suffix = None

Definition at line 38 of file Step.py.

◆ depends_on_exec

bool python.TrigValSteering.Step.Step.depends_on_exec = False

Definition at line 45 of file Step.py.

◆ depends_on_previous

bool python.TrigValSteering.Step.Step.depends_on_previous = False

Definition at line 44 of file Step.py.

◆ executable

python.TrigValSteering.Step.Step.executable = None

Definition at line 35 of file Step.py.

◆ log

python.TrigValSteering.Step.Step.log = get_logger()

Definition at line 32 of file Step.py.

◆ log_file_name

python.TrigValSteering.Step.Step.log_file_name = None

Definition at line 40 of file Step.py.

◆ name

python.TrigValSteering.Step.Step.name = name

Definition at line 33 of file Step.py.

◆ output_stream

python.TrigValSteering.Step.Step.output_stream = self.OutputStream.FILE_ONLY

Definition at line 39 of file Step.py.

◆ prmon

bool python.TrigValSteering.Step.Step.prmon = False

Definition at line 47 of file Step.py.

◆ prmon_interval

int python.TrigValSteering.Step.Step.prmon_interval = 5

Definition at line 48 of file Step.py.

◆ required

bool python.TrigValSteering.Step.Step.required = False

Definition at line 43 of file Step.py.

◆ timeout

python.TrigValSteering.Step.Step.timeout = None

Definition at line 46 of file Step.py.

◆ type

python.TrigValSteering.Step.Step.type = None

Definition at line 34 of file Step.py.

◆ workdir

python.TrigValSteering.Step.Step.workdir = None

Definition at line 49 of file Step.py.


The documentation for this class was generated from the following file: