Example #1
0
def fork(nprocs=None):
    '''continue as ``nprocs`` parallel processes by forking ``nprocs-1`` times

  If ``nprocs`` exceeds the configured ``maxprocs`` than it will silently be
  capped. It is up to the user to prepare shared memory and/or locks for
  inter-process communication. As a safety measure nested forks are blocked by
  limiting nprocs to 1; all secondary forks will be silently ignored.
  '''

    if nprocs is None or nprocs > _maxprocs.value:
        nprocs = _maxprocs.value
    if nprocs <= 1:
        yield 0
        return
    if not hasattr(os, 'fork'):
        warnings.warn('fork is unavailable on this platform')
        yield 0
        return
    amchild = False
    try:
        child_pids = []
        for procid in builtins.range(1, nprocs):
            pid = os.fork()
            if not pid:  # pragma: no cover
                amchild = True
                signal.signal(
                    signal.SIGINT,
                    signal.SIG_IGN)  # disable sigint (ctrl+c) handler
                treelog.current = treelog.NullLog()  # silence treelog
                break
            child_pids.append(pid)
        else:
            procid = 0
        with maxprocs(1):
            yield procid
    except BaseException as e:
        if amchild:  # pragma: no cover
            try:
                print('[parallel.fork] exception in child process:', e)
            finally:
                os._exit(1)  # communicate failure to main process
        for pid in child_pids:  # kill all child processes
            os.kill(pid, signal.SIGKILL)
        raise
    else:
        if amchild:  # pragma: no cover
            os._exit(0)  # communicate success to main process
        with treelog.context('waiting for child processes'):
            nfails = sum(not _wait(pid) for pid in child_pids)
        if nfails:  # failure in child process: raise exception
            raise Exception('fork failed in {} out of {} processes'.format(
                nfails, nprocs))
    finally:
        if amchild:  # pragma: no cover
            os._exit(1)  # failsafe
Example #2
0
def fork(nprocs=None):
    '''continue as ``nprocs`` parallel processes by forking ``nprocs-1`` times

  If ``nprocs`` exceeds the configured ``maxprocs`` than it will silently be
  capped. It is up to the user to prepare shared memory and/or locks for
  inter-process communication. As a safety measure nested forks are blocked by
  limiting nprocs to 1; all secondary forks will be silently ignored.
  '''

    if nprocs is None or nprocs > _maxprocs:
        nprocs = _maxprocs
    if nprocs == 1:
        yield 0
        return
    if not hasattr(os, 'fork'):
        log.warning('fork is unavailable on this platform')
        yield 0
        return
    child_pids = []
    try:
        fail = 1
        for procid in builtins.range(1, nprocs):
            pid = os.fork()
            if not pid:
                signal.signal(
                    signal.SIGINT,
                    signal.SIG_IGN)  # disable sigint (ctrl+c) handler
                log.current = log.NullLog()
                break
            child_pids.append(pid)
        else:
            procid = 0
        with maxprocs(1):
            yield procid
        fail = 0
    finally:
        if procid:  # before anything else can fail:
            os._exit(fail)  # communicate exit status to main process
        nfails = fail + sum(os.waitpid(pid, 0)[1] != 0 for pid in child_pids)
        if fail:  # failure in main process: exception has been reraised
            log.error(
                'fork failed in {} out of {} processes; reraising exception for main process'
                .format(nfails, nprocs))
        elif nfails:  # failure in child process: raise exception
            raise Exception('fork failed in {} out of {} processes'.format(
                nfails, _maxprocs))
Example #3
0
 def output_tester(self):
     with self.assertSilent():
         yield treelog.NullLog()