ATLAS Offline Software
Classes | Public Member Functions | Public Attributes | Private Member Functions | List of all members
python.TrigValSteering.Step.Step Class Reference
Inheritance diagram for python.TrigValSteering.Step.Step:
Collaboration diagram for python.TrigValSteering.Step.Step:

Classes

class  OutputStream
 

Public Member Functions

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

Public Attributes

 log
 
 name
 
 type
 
 executable
 
 args
 
 cmd_prefix
 
 cmd_suffix
 
 output_stream
 
 log_file_name
 
 result
 
 auto_report_result
 
 required
 
 depends_on_previous
 
 depends_on_exec
 
 timeout
 
 prmon
 
 prmon_interval
 
 workdir
 

Private Member Functions

def __trace_and_kill (self, pid, signal, backtrace_list)
 
def __execute_with_timeout (self, cmd, timeout_sec)
 
def __start_prmon (self)
 
def __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.

Constructor & Destructor Documentation

◆ __init__()

def 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()

def 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()

def 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 

◆ __stop_prmon()

def 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()

def 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()

def 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 

◆ get_log_file_name()

def 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()

def 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()

def 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()

def 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 

Member Data Documentation

◆ args

python.TrigValSteering.Step.Step.args

Definition at line 36 of file Step.py.

◆ auto_report_result

python.TrigValSteering.Step.Step.auto_report_result

Definition at line 42 of file Step.py.

◆ cmd_prefix

python.TrigValSteering.Step.Step.cmd_prefix

Definition at line 37 of file Step.py.

◆ cmd_suffix

python.TrigValSteering.Step.Step.cmd_suffix

Definition at line 38 of file Step.py.

◆ depends_on_exec

python.TrigValSteering.Step.Step.depends_on_exec

Definition at line 45 of file Step.py.

◆ depends_on_previous

python.TrigValSteering.Step.Step.depends_on_previous

Definition at line 44 of file Step.py.

◆ executable

python.TrigValSteering.Step.Step.executable

Definition at line 35 of file Step.py.

◆ log

python.TrigValSteering.Step.Step.log

Definition at line 32 of file Step.py.

◆ log_file_name

python.TrigValSteering.Step.Step.log_file_name

Definition at line 40 of file Step.py.

◆ name

python.TrigValSteering.Step.Step.name

Definition at line 33 of file Step.py.

◆ output_stream

python.TrigValSteering.Step.Step.output_stream

Definition at line 39 of file Step.py.

◆ prmon

python.TrigValSteering.Step.Step.prmon

Definition at line 47 of file Step.py.

◆ prmon_interval

python.TrigValSteering.Step.Step.prmon_interval

Definition at line 48 of file Step.py.

◆ required

python.TrigValSteering.Step.Step.required

Definition at line 43 of file Step.py.

◆ result

python.TrigValSteering.Step.Step.result

Definition at line 41 of file Step.py.

◆ timeout

python.TrigValSteering.Step.Step.timeout

Definition at line 46 of file Step.py.

◆ type

python.TrigValSteering.Step.Step.type

Definition at line 34 of file Step.py.

◆ workdir

python.TrigValSteering.Step.Step.workdir

Definition at line 49 of file Step.py.


The documentation for this class was generated from the following file:
grepfile.info
info
Definition: grepfile.py:38
read
IovVectorMap_t read(const Folder &theFolder, const SelectionCriterion &choice, const unsigned int limit=10)
Definition: openCoraCool.cxx:569
Timer
Definition: main_benchmark.cxx:76
vtune_athena.format
format
Definition: vtune_athena.py:14
configure
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)
Definition: TrigGlobEffCorrValidation.cxx:514
run
int run(int argc, char *argv[])
Definition: ttree2hdf5.cxx:28
python.TrigValSteering.Common.running_in_CI
def running_in_CI()
Definition: Common.py:78
python.logfiles.grep_with_context
def grep_with_context(f, pattern, lines=100, print_head=True, print_tail=True)
Definition: logfiles.py:10
TCS::join
std::string join(const std::vector< std::string > &v, const char c=',')
Definition: Trigger/TrigT1/L1Topo/L1TopoCommon/Root/StringUtils.cxx:10
debug
const bool debug
Definition: MakeUncertaintyPlots.cxx:53
python.PerfMonSerializer.decode
def decode(s)
Definition: PerfMonSerializer.py:388
TrigJetMonitorAlgorithm.items
items
Definition: TrigJetMonitorAlgorithm.py:79
python.processes.powheg.ZZ.ZZ.__init__
def __init__(self, base_directory, **kwargs)
Constructor: all process options are set here.
Definition: ZZ.py:18
Trk::open
@ open
Definition: BinningType.h:40
python.TrigARTUtils.remember_cwd
def remember_cwd()
Definition: TrigARTUtils.py:50
python.TrigValSteering.Common.get_logger
def get_logger()
Definition: Common.py:33
str
Definition: BTagTrackIpAccessor.cxx:11
python.TrigValSteering.Common.art_result
def art_result(result, name)
Definition: Common.py:42
error
Definition: IImpactPoint3dEstimator.h:70