Mercurial > hg
changeset 40497:3fbfbc8c9f82
remotefilelog: transplant runbgcommand to procutil
While cleaning up the deprecated runshellcommand I noticed a
near-clone of this in logtoprocess, so I'm standardizing on what
appears to be the newer one by moving it to procutil.
Differential Revision: https://phab.mercurial-scm.org/D4938
author | Augie Fackler <augie@google.com> |
---|---|
date | Wed, 03 Oct 2018 14:01:04 -0400 |
parents | 60eb35b0c11c |
children | 8fab95aa5280 |
files | hgext/remotefilelog/extutil.py hgext/remotefilelog/repack.py hgext/remotefilelog/shallowrepo.py mercurial/utils/procutil.py |
diffstat | 4 files changed, 74 insertions(+), 76 deletions(-) [+] |
line wrap: on
line diff
--- a/hgext/remotefilelog/extutil.py Wed Oct 03 13:54:45 2018 -0400 +++ b/hgext/remotefilelog/extutil.py Wed Oct 03 14:01:04 2018 -0400 @@ -10,88 +10,15 @@ import contextlib import errno import os -import subprocess import time from mercurial import ( error, lock as lockmod, - pycompat, util, vfs as vfsmod, ) -if pycompat.iswindows: - # no fork on Windows, but we can create a detached process - # https://msdn.microsoft.com/en-us/library/windows/desktop/ms684863.aspx - # No stdlib constant exists for this value - DETACHED_PROCESS = 0x00000008 - _creationflags = DETACHED_PROCESS | subprocess.CREATE_NEW_PROCESS_GROUP - - def runbgcommand(script, env, shell=False, stdout=None, stderr=None): - '''Spawn a command without waiting for it to finish.''' - # we can't use close_fds *and* redirect stdin. I'm not sure that we - # need to because the detached process has no console connection. - subprocess.Popen( - script, shell=shell, env=env, close_fds=True, - creationflags=_creationflags, stdout=stdout, stderr=stderr) -else: - def runbgcommand(cmd, env, shell=False, stdout=None, stderr=None): - '''Spawn a command without waiting for it to finish.''' - # double-fork to completely detach from the parent process - # based on http://code.activestate.com/recipes/278731 - pid = os.fork() - if pid: - # Parent process - (_pid, status) = os.waitpid(pid, 0) - if os.WIFEXITED(status): - returncode = os.WEXITSTATUS(status) - else: - returncode = -os.WTERMSIG(status) - if returncode != 0: - # The child process's return code is 0 on success, an errno - # value on failure, or 255 if we don't have a valid errno - # value. - # - # (It would be slightly nicer to return the full exception info - # over a pipe as the subprocess module does. For now it - # doesn't seem worth adding that complexity here, though.) - if returncode == 255: - returncode = errno.EINVAL - raise OSError(returncode, 'error running %r: %s' % - (cmd, os.strerror(returncode))) - return - - returncode = 255 - try: - # Start a new session - os.setsid() - - stdin = open(os.devnull, 'r') - if stdout is None: - stdout = open(os.devnull, 'w') - if stderr is None: - stderr = open(os.devnull, 'w') - - # connect stdin to devnull to make sure the subprocess can't - # muck up that stream for mercurial. - subprocess.Popen( - cmd, shell=shell, env=env, close_fds=True, - stdin=stdin, stdout=stdout, stderr=stderr) - returncode = 0 - except EnvironmentError as ex: - returncode = (ex.errno & 0xff) - if returncode == 0: - # This shouldn't happen, but just in case make sure the - # return code is never 0 here. - returncode = 255 - except Exception: - returncode = 255 - finally: - # mission accomplished, this child needs to exit and not - # continue the hg process here. - os._exit(returncode) - @contextlib.contextmanager def flock(lockpath, description, timeout=-1): """A flock based lock object. Currently it is always non-blocking.
--- a/hgext/remotefilelog/repack.py Wed Oct 03 13:54:45 2018 -0400 +++ b/hgext/remotefilelog/repack.py Wed Oct 03 14:01:04 2018 -0400 @@ -50,7 +50,7 @@ if packsonly: cmd.append('--packsonly') repo.ui.warn(msg) - extutil.runbgcommand(cmd, encoding.environ) + procutil.runbgcommand(cmd, encoding.environ) def fullrepack(repo, options=None): """If ``packsonly`` is True, stores creating only loose objects are skipped.
--- a/hgext/remotefilelog/shallowrepo.py Wed Oct 03 13:54:45 2018 -0400 +++ b/hgext/remotefilelog/shallowrepo.py Wed Oct 03 14:01:04 2018 -0400 @@ -25,7 +25,6 @@ constants, contentstore, datapack, - extutil, fileserverclient, historypack, metadatastore, @@ -199,7 +198,7 @@ cmd.append('--repack') if revs: cmd += ['-r', revs] - extutil.runbgcommand(cmd, encoding.environ) + procutil.runbgcommand(cmd, encoding.environ) def prefetch(self, revs, base=None, pats=None, opts=None): """Prefetches all the necessary file revisions for the given revs
--- a/mercurial/utils/procutil.py Wed Oct 03 13:54:45 2018 -0400 +++ b/mercurial/utils/procutil.py Wed Oct 03 14:01:04 2018 -0400 @@ -10,6 +10,7 @@ from __future__ import absolute_import import contextlib +import errno import imp import io import os @@ -467,3 +468,74 @@ signal.signal(signal.SIGINT, oldsiginthandler[0]) if shouldbail: raise KeyboardInterrupt + +if pycompat.iswindows: + # no fork on Windows, but we can create a detached process + # https://msdn.microsoft.com/en-us/library/windows/desktop/ms684863.aspx + # No stdlib constant exists for this value + DETACHED_PROCESS = 0x00000008 + _creationflags = DETACHED_PROCESS | subprocess.CREATE_NEW_PROCESS_GROUP + + def runbgcommand(script, env, shell=False, stdout=None, stderr=None): + '''Spawn a command without waiting for it to finish.''' + # we can't use close_fds *and* redirect stdin. I'm not sure that we + # need to because the detached process has no console connection. + subprocess.Popen( + script, shell=shell, env=env, close_fds=True, + creationflags=_creationflags, stdout=stdout, stderr=stderr) +else: + def runbgcommand(cmd, env, shell=False, stdout=None, stderr=None): + '''Spawn a command without waiting for it to finish.''' + # double-fork to completely detach from the parent process + # based on http://code.activestate.com/recipes/278731 + pid = os.fork() + if pid: + # Parent process + (_pid, status) = os.waitpid(pid, 0) + if os.WIFEXITED(status): + returncode = os.WEXITSTATUS(status) + else: + returncode = -os.WTERMSIG(status) + if returncode != 0: + # The child process's return code is 0 on success, an errno + # value on failure, or 255 if we don't have a valid errno + # value. + # + # (It would be slightly nicer to return the full exception info + # over a pipe as the subprocess module does. For now it + # doesn't seem worth adding that complexity here, though.) + if returncode == 255: + returncode = errno.EINVAL + raise OSError(returncode, 'error running %r: %s' % + (cmd, os.strerror(returncode))) + return + + returncode = 255 + try: + # Start a new session + os.setsid() + + stdin = open(os.devnull, 'r') + if stdout is None: + stdout = open(os.devnull, 'w') + if stderr is None: + stderr = open(os.devnull, 'w') + + # connect stdin to devnull to make sure the subprocess can't + # muck up that stream for mercurial. + subprocess.Popen( + cmd, shell=shell, env=env, close_fds=True, + stdin=stdin, stdout=stdout, stderr=stderr) + returncode = 0 + except EnvironmentError as ex: + returncode = (ex.errno & 0xff) + if returncode == 0: + # This shouldn't happen, but just in case make sure the + # return code is never 0 here. + returncode = 255 + except Exception: + returncode = 255 + finally: + # mission accomplished, this child needs to exit and not + # continue the hg process here. + os._exit(returncode)