# **************************************************************************
# *
# * Authors: J.M. De la Rosa Trevin (jmdelarosa@cnb.csic.es)
# * Laura del Cano (ldelcano@cnb.csic.es)
# *
# * Unidad de Bioinformatica of Centro Nacional de Biotecnologia , CSIC
# *
# * This program is free software; you can redistribute it and/or modify
# * it under the terms of the GNU General Public License as published by
# * the Free Software Foundation; either version 3 of the License, or
# * (at your option) any later version.
# *
# * This program is distributed in the hope that it will be useful,
# * but WITHOUT ANY WARRANTY; without even the implied warranty of
# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# * GNU General Public License for more details.
# *
# * You should have received a copy of the GNU General Public License
# * along with this program; if not, write to the Free Software
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
# * 02111-1307 USA
# *
# * All comments concerning this program package may be sent to the
# * e-mail address 'scipion@cnb.csic.es'
# *
# **************************************************************************
"""
This module handles process execution
"""
import logging
logger = logging.getLogger(__name__)
import sys
from subprocess import check_call
import psutil
from .utils import greenStr
from pyworkflow import Config
# The job should be launched from the working directory!
[docs]def runJob(log, programname, params,
numberOfMpi=1, numberOfThreads=1,
hostConfig=None, env=None, cwd=None, gpuList=None, executable=None):
command = buildRunCommand(programname, params, numberOfMpi, hostConfig,
env, gpuList=gpuList)
if log is None:
log = logger
log.info("** Running command: **")
log.info(greenStr(command))
return runCommand(command, env=env, cwd=cwd, executable=executable)
[docs]def runCommand(command, env=None, cwd=None, executable=None):
""" Execute command with given environment env and directory cwd """
# First let us create core dumps if in debug mode
if Config.debugOn():
import resource
resource.setrlimit(resource.RLIMIT_CORE,
(resource.RLIM_INFINITY, resource.RLIM_INFINITY))
# This is like "ulimit -u 99999999", so we can create core dumps
# TODO: maybe have to set PBS_NODEFILE in case it is used by "command"
# (useful for example with gnu parallel)
check_call(command, shell=True, stdout=sys.stdout, stderr=sys.stderr,
env=env, cwd=cwd, executable=executable)
# It would be nice to avoid shell=True and calling buildRunCommand()...
[docs]def buildRunCommand(programname, params, numberOfMpi, hostConfig=None,
env=None, gpuList=None):
""" Return a string with the command line to run """
# Convert our list of params to a string, with each element escaped
# with "" in case there are spaces.
if not isinstance(params, str):
params = ' '.join('"%s"' % p for p in params)
if gpuList:
params = params % {'GPU': ' '.join(str(g) for g in gpuList)}
if "CUDA_VISIBLE_DEVICES" in programname:
sep = "," if len(gpuList) > 1 else ""
programname = programname % {'GPU': sep.join(str(g) for g in gpuList)}
prepend = '' if env is None else env.getPrepend()
if numberOfMpi <= 1:
return '%s %s %s' % (prepend, programname, params)
else:
assert hostConfig is not None, 'hostConfig needed to launch MPI processes.'
if programname.startswith('xmipp') and not programname.startswith('xmipp_mpi'):
programname = programname.replace('xmipp', 'xmipp_mpi')
mpiFlags = '' if env is None else env.get('SCIPION_MPI_FLAGS', '')
mpiCmd = hostConfig.mpiCommand.get() % {
'JOB_NODES': numberOfMpi,
'COMMAND': "%s `which %s` %s" % (mpiFlags, programname, params),
}
return '%s %s' % (prepend, mpiCmd)
[docs]def killWithChilds(pid):
""" Kill the process with given pid and all children processes.
:param pid: the process id to terminate
"""
proc = psutil.Process(pid)
for c in proc.children(recursive=True):
if c.pid is not None:
logger.info("Terminating child pid: %d" % c.pid)
c.kill()
logger.info("Terminating process pid: %s" % pid)
if pid is None:
logger.warning("Got None PID!!!")
else:
proc.kill()
[docs]def isProcessAlive(pid):
try:
psutil.Process(pid)
return True
except Exception:
return False