D4938: remotefilelog: transplant runbgcommand to procutil

durin42 (Augie Fackler) phabricator at mercurial-scm.org
Thu Oct 11 12:21:37 UTC 2018


durin42 created this revision.
Herald added a subscriber: mercurial-devel.
Herald added a reviewer: hg-reviewers.

REVISION SUMMARY
  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.

REPOSITORY
  rHG Mercurial

REVISION DETAIL
  https://phab.mercurial-scm.org/D4938

AFFECTED FILES
  hgext/remotefilelog/extutil.py
  hgext/remotefilelog/repack.py
  hgext/remotefilelog/shallowrepo.py
  mercurial/utils/procutil.py

CHANGE DETAILS

diff --git a/mercurial/utils/procutil.py b/mercurial/utils/procutil.py
--- a/mercurial/utils/procutil.py
+++ b/mercurial/utils/procutil.py
@@ -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)
diff --git a/hgext/remotefilelog/shallowrepo.py b/hgext/remotefilelog/shallowrepo.py
--- a/hgext/remotefilelog/shallowrepo.py
+++ b/hgext/remotefilelog/shallowrepo.py
@@ -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
diff --git a/hgext/remotefilelog/repack.py b/hgext/remotefilelog/repack.py
--- a/hgext/remotefilelog/repack.py
+++ b/hgext/remotefilelog/repack.py
@@ -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.
diff --git a/hgext/remotefilelog/extutil.py b/hgext/remotefilelog/extutil.py
--- a/hgext/remotefilelog/extutil.py
+++ b/hgext/remotefilelog/extutil.py
@@ -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.



To: durin42, #hg-reviewers
Cc: mercurial-devel


More information about the Mercurial-devel mailing list