3 from __future__
import print_function
6 from tempfile
import mkstemp
11 Remove from the arguments the presence of the profiler and its output in 12 order to relaunch the script w/o infinite loops. 14 >>> getArgsWithoutoProfilerInfo(['--profilerName', 'igprof', 'myopts.py']) 17 >>> getArgsWithoutoProfilerInfo(['--profilerName=igprof', 'myopts.py']) 20 >>> getArgsWithoutoProfilerInfo(['--profilerName', 'igprof', '--profilerExtraOptions', 'a b c', 'myopts.py']) 23 >>> getArgsWithoutoProfilerInfo(['--profilerName', 'igprof', '--options', 'a b c', 'myopts.py']) 24 ['--options', 'a b c', 'myopts.py'] 30 if o.startswith(
'--profile'):
39 ''' Adds a list of libraries to LD_PRELOAD ''' 40 preload = os.environ.get(
"LD_PRELOAD",
"")
42 preload = preload.replace(
" ",
":").split(
":")
46 for libname
in set(preload).intersection(newpreload):
48 "Ignoring preload of library %s because it is " 49 "already in LD_PRELOAD.", libname)
52 libname
for libname
in newpreload
if libname
not in set(preload)
57 preload =
":".join(preload)
58 os.environ[
"LD_PRELOAD"] = preload
59 logging.info(
"Setting LD_PRELOAD='%s'", preload)
66 Convert the given path to a real path if the pointed file exists, otherwise 69 path = os.path.normpath(os.path.expandvars(path))
70 if os.path.exists(path):
71 path = os.path.realpath(path)
77 _qmt_tmp_opt_files = []
82 Given a .qmt file, return the command line arguments of the corresponding 85 from xml.etree
import ElementTree
as ET
86 global _qmt_tmp_opt_files
88 qmt = ET.parse(qmtfile)
89 args = [a.text
for a
in qmt.findall(
"argument[@name='args']//text")]
90 options = qmt.find(
"argument[@name='options']/text")
92 if options
is not None:
93 from tempfile
import NamedTemporaryFile
96 r"from\s+Gaudi.Configuration\s+import\s+\*" 97 r"|from\s+Configurables\s+import", options.text):
98 tmp_opts = NamedTemporaryFile(suffix=
'.py')
100 tmp_opts = NamedTemporaryFile(suffix=
'.opts')
101 tmp_opts.write(options.text.encode(
'ascii'))
103 args.append(tmp_opts.name)
104 _qmt_tmp_opt_files.append(tmp_opts)
108 qmtfile = os.path.abspath(qmtfile)
109 if 'qmtest' in qmtfile.split(os.path.sep):
112 while os.path.basename(testdir) !=
'qmtest':
113 testdir = os.path.dirname(testdir)
117 old_cwd = os.getcwd()
119 args =
map(rationalizepath, args)
126 if __name__ ==
"__main__":
128 if os.environ.get(
'LC_ALL') !=
'C':
129 print(
'# setting LC_ALL to "C"')
131 os.environ[
'LC_ALL'] =
'C' 133 from optparse
import OptionParser
134 parser = OptionParser(usage=
"%prog [options] <opts_file> ...")
139 help=
"do not run the application, just parse option files")
146 help=
"DEPRECATED: use '--output file.pkl' instead. Write " 147 "the parsed options as a pickle file (static option " 153 help=
"print the parsed options")
157 help=
"format printed options in old option files style")
161 help=
"print all the option (even if equal to default)")
172 help=
"start the application in parallel mode using NCPUS processes. " 173 "0 => serial mode (default), -1 => use all CPUs")
176 """Add the option line to a list together with its position in the 179 parser.values.options.append((len(parser.largs), value))
187 help=
"add a single line (Python) option to the configuration. " 188 "All options lines are executed, one after the other, in " 191 "--no-conf-user-apply",
193 help=
"disable the automatic application of configurable " 194 "users (for backward compatibility)")
196 "--old-conf-user-apply",
198 help=
"use the old logic when applying ConfigurableUsers " 199 "(with bug #103803) [default]")
201 "--new-conf-user-apply",
202 action=
"store_false",
203 dest=
"old_conf_user_apply",
204 help=
"use the new (correct) logic when applying " 205 "ConfigurableUsers (fixed bug #103803), can be " 206 "turned on also with the environment variable " 207 "GAUDI_FIXED_APPLY_CONF")
213 help=
"dump the configuration to a file. The format of " 214 "the options is determined by the extension of the " 215 "file name: .pkl = pickle, .py = python, .opts = " 216 "old style options. The python format cannot be " 217 "used to run the application and it contains the " 218 "same dictionary printed with -v")
224 help=
"Python options to be executed after the ConfigurableUser " 226 "All options lines are executed, one after the other, in " 229 "--debug", action=
"store_true", help=
"enable some debug print-out")
230 parser.add_option(
"--gdb", action=
"store_true", help=
"attach gdb")
232 "--printsequence", action=
"store_true", help=
"print the sequence")
233 if not sys.platform.startswith(
"win"):
239 help=
"Use the Google malloc replacement. The environment " 240 "variable TCMALLOCLIB can be used to specify a different " 241 "name for the library (the default is libtcmalloc.so)")
245 help=
"Allow pre-loading of special libraries (e.g. Google " 246 "profiling libraries).")
252 "Select one profiler among: igprofPerf, igprofMem and valgrind<toolname>" 259 help=
"Specify the name of the output file for the profiler output")
263 "--profilerExtraOptions",
266 "Specify additional options for the profiler. The '--' string should be expressed as '__' (--my-opt becomes __my-opt)" 272 help=
'when this option is enabled, the options are parsed' 273 ' and stored in a temporary file, then the job is ' 274 'restarted using that file as input (to save ' 280 "Save gaudi process information to the file specified (in JSON format)" 284 help=
'name of the Gaudi::Application to use [default: %default]')
291 profilerExtraOptions=
'',
295 old_conf_user_apply=
'GAUDI_FIXED_APPLY_CONF' not in os.environ,
297 application=
'Gaudi::Application')
301 for a
in sys.argv[1:]:
302 if a.endswith(
'.qmt')
and os.path.exists(a):
306 if argv != sys.argv[1:]:
307 print(
'# Running', sys.argv[0],
'with arguments', argv)
309 opts, args = parser.parse_args(args=argv)
315 from multiprocessing
import cpu_count
316 sys_cpus = cpu_count()
317 if opts.ncpus > sys_cpus:
318 s =
"Invalid value : --ncpus : only %i cpus available" % sys_cpus
320 elif opts.ncpus < -1:
321 s =
"Invalid value : --ncpus must be integer >= -1" 338 level = logging.DEBUG
340 root_logger = logging.getLogger()
343 sanitizer = os.environ.get(
"PRELOAD_SANITIZER_LIB",
"")
345 if sanitizer
not in os.environ.get(
"LD_PRELOAD",
""):
346 opts.preload.insert(0, sanitizer)
347 os.environ[
"PRELOAD_SANITIZER_LIB"] =
"" 353 logging.warning(
"tcmalloc preload disabled when using a sanitizer")
356 0, os.environ.get(
"TCMALLOCLIB",
"libtcmalloc.so"))
360 preload = os.environ.get(
"LD_PRELOAD",
"")
362 preload = preload.replace(
" ",
":").split(
":")
365 for libname
in set(preload).intersection(opts.preload):
367 "Ignoring preload of library %s because it is " 368 "already in LD_PRELOAD.", libname)
370 libname
for libname
in opts.preload
if libname
not in set(preload)
374 preload =
":".join(preload)
375 os.environ[
"LD_PRELOAD"] = preload
376 logging.info(
"Restarting with LD_PRELOAD='%s'", preload)
381 if a !=
'-T' and not '--tcmalloc'.startswith(a)
383 os.execv(sys.executable, [sys.executable] + args)
386 if opts.profilerName:
387 profilerName = opts.profilerName
388 profilerExecName =
"" 389 profilerOutput = opts.profilerOutput
or (profilerName +
".output")
394 igprofPerfOptions =
"-d -pp -z -o igprof.pp.gz".split()
397 if profilerName ==
"igprof":
398 if not opts.profilerOutput:
399 profilerOutput +=
".profile.gz" 400 profilerOptions =
"-d -z -o %s" % profilerOutput
401 profilerExecName =
"igprof" 403 elif profilerName ==
"igprofPerf":
404 if not opts.profilerOutput:
405 profilerOutput +=
".pp.gz" 406 profilerOptions =
"-d -pp -z -o %s" % profilerOutput
407 profilerExecName =
"igprof" 409 elif profilerName ==
"igprofMem":
410 if not opts.profilerOutput:
411 profilerOutput +=
".mp.gz" 412 profilerOptions =
"-d -mp -z -o %s" % profilerOutput
413 profilerExecName =
"igprof" 415 elif "valgrind" in profilerName:
417 if not opts.profilerOutput:
418 profilerOutput +=
".log" 419 toolname = profilerName.replace(
'valgrind',
'')
420 outoption =
"--log-file" 421 if toolname
in (
"massif",
"callgrind",
"cachegrind"):
422 outoption =
"--%s-out-file" % toolname
423 profilerOptions =
"--tool=%s %s=%s" % (toolname, outoption,
425 profilerExecName =
"valgrind" 427 elif profilerName ==
"jemalloc":
429 0, os.environ.get(
"JEMALLOCLIB",
"libjemalloc.so"))
430 os.environ[
'MALLOC_CONF'] =
"prof:true,prof_leak:true" 432 root_logger.warning(
"Profiler %s not recognized!" % profilerName)
435 if opts.profilerExtraOptions !=
"":
436 profilerExtraOptions = opts.profilerExtraOptions
437 profilerExtraOptions = profilerExtraOptions.replace(
"__",
"--")
438 profilerOptions +=
" %s" % profilerExtraOptions
442 import distutils.spawn
443 profilerPath = distutils.spawn.find_executable(profilerExecName)
446 "Cannot locate profiler %s" % profilerExecName)
449 root_logger.info(
"------ Profiling options are on ------ \n" 451 " o Options: '%s'.\n" 452 " o Output: %s" % (profilerExecName
or profilerName,
453 profilerOptions, profilerOutput))
463 profilerOptions +=
" python" 466 arglist = [profilerPath] + profilerOptions.split() + args
467 arglist = [a
for a
in arglist
if a !=
'']
471 os.execv(profilerPath, arglist)
473 arglist = [a
for a
in sys.argv
if not a.startswith(
"--profiler")]
474 os.execv(sys.executable, [sys.executable] + arglist)
478 if opts.pickle_output:
481 "Conflicting options: use only --pickle-output or --output")
485 "--pickle-output is deprecated, use --output instead")
486 opts.output = opts.pickle_output
494 options = [
"importOptions(%r)" % f
for f
in args]
497 optlines = list(opts.options)
500 for pos, l
in optlines:
501 options.insert(pos, l)
512 RuntimeError(
"GaudiPython cannot be used in option files"))
516 if 'GAUDI_TEMP_OPTS_FILE' in os.environ:
517 options = [
'importOptions(%r)' % os.environ[
'GAUDI_TEMP_OPTS_FILE']]
524 exec (
"from Gaudi.Configuration import *", g, l)
529 import GaudiKernel.Proxy.Configurable
530 if opts.no_conf_user_apply:
531 logging.info(
"Disabling automatic apply of ConfigurableUser")
533 GaudiKernel.Proxy.Configurable._appliedConfigurableUsers_ =
True 536 if opts.old_conf_user_apply:
537 from GaudiKernel.Proxy.Configurable
import applyConfigurableUsers_old
as applyConfigurableUsers
539 from GaudiKernel.Proxy.Configurable
import applyConfigurableUsers
543 if opts.post_options:
546 exec (
"from Gaudi.Configuration import *", g, l)
547 for o
in opts.post_options:
551 if 'GAUDI_TEMP_OPTS_FILE' in os.environ:
552 os.remove(os.environ[
'GAUDI_TEMP_OPTS_FILE'])
553 opts.use_temp_opts =
False 555 if opts.verbose
and not opts.use_temp_opts:
556 c.printconfig(opts.old_opts, opts.all_opts)
558 c.writeconfig(opts.output, opts.all_opts)
560 if opts.use_temp_opts:
561 fd, tmpfile = mkstemp(
'.opts')
563 c.writeconfig(tmpfile, opts.all_opts)
564 os.environ[
'GAUDI_TEMP_OPTS_FILE'] = tmpfile
565 logging.info(
'Restarting from pre-parsed options')
566 os.execv(sys.executable, [sys.executable] + sys.argv)
568 c.printsequence = opts.printsequence
569 if opts.printsequence:
572 "--printsequence not supported with --ncpus: ignored")
575 "--printsequence not supported with --dry-run: ignored")
577 c.application = opts.application
580 del sys.modules[
"GaudiPython"]
584 retcode = c.run(opts.gdb, opts.ncpus)
588 if opts.run_info_file:
592 run_info[
"pid"] = os.getpid()
593 run_info[
"retcode"] = retcode
594 if os.path.exists(
'/proc/self/exe'):
596 run_info[
"exe"] = os.readlink(
'/proc/self/exe')
598 logging.info(
"Saving run info to: %s" % opts.run_info_file)
599 with open(opts.run_info_file,
"w")
as f:
600 json.dump(run_info, f)
def __init__(self, exception)
def option_cb(option, opt, value, parser)
def rationalizepath(path)
def applyConfigurableUsers()
def getArgsFromQmt(qmtfile)
def InstallRootLoggingHandler(prefix=None, level=None, stream=None, with_time=False)
struct GAUDI_API map
Parametrisation class for map-like implementation.
def getArgsWithoutoProfilerInfo(args)
def __getattr__(self, *args, **kwargs)
def setLibraryPreload(newpreload)