##// END OF EJS Templates
remotefilelog: transplant runbgcommand to procutil...
Augie Fackler -
r40532:3fbfbc8c default
parent child Browse files
Show More
@@ -10,88 +10,15 b' from __future__ import absolute_import'
10 10 import contextlib
11 11 import errno
12 12 import os
13 import subprocess
14 13 import time
15 14
16 15 from mercurial import (
17 16 error,
18 17 lock as lockmod,
19 pycompat,
20 18 util,
21 19 vfs as vfsmod,
22 20 )
23 21
24 if pycompat.iswindows:
25 # no fork on Windows, but we can create a detached process
26 # https://msdn.microsoft.com/en-us/library/windows/desktop/ms684863.aspx
27 # No stdlib constant exists for this value
28 DETACHED_PROCESS = 0x00000008
29 _creationflags = DETACHED_PROCESS | subprocess.CREATE_NEW_PROCESS_GROUP
30
31 def runbgcommand(script, env, shell=False, stdout=None, stderr=None):
32 '''Spawn a command without waiting for it to finish.'''
33 # we can't use close_fds *and* redirect stdin. I'm not sure that we
34 # need to because the detached process has no console connection.
35 subprocess.Popen(
36 script, shell=shell, env=env, close_fds=True,
37 creationflags=_creationflags, stdout=stdout, stderr=stderr)
38 else:
39 def runbgcommand(cmd, env, shell=False, stdout=None, stderr=None):
40 '''Spawn a command without waiting for it to finish.'''
41 # double-fork to completely detach from the parent process
42 # based on http://code.activestate.com/recipes/278731
43 pid = os.fork()
44 if pid:
45 # Parent process
46 (_pid, status) = os.waitpid(pid, 0)
47 if os.WIFEXITED(status):
48 returncode = os.WEXITSTATUS(status)
49 else:
50 returncode = -os.WTERMSIG(status)
51 if returncode != 0:
52 # The child process's return code is 0 on success, an errno
53 # value on failure, or 255 if we don't have a valid errno
54 # value.
55 #
56 # (It would be slightly nicer to return the full exception info
57 # over a pipe as the subprocess module does. For now it
58 # doesn't seem worth adding that complexity here, though.)
59 if returncode == 255:
60 returncode = errno.EINVAL
61 raise OSError(returncode, 'error running %r: %s' %
62 (cmd, os.strerror(returncode)))
63 return
64
65 returncode = 255
66 try:
67 # Start a new session
68 os.setsid()
69
70 stdin = open(os.devnull, 'r')
71 if stdout is None:
72 stdout = open(os.devnull, 'w')
73 if stderr is None:
74 stderr = open(os.devnull, 'w')
75
76 # connect stdin to devnull to make sure the subprocess can't
77 # muck up that stream for mercurial.
78 subprocess.Popen(
79 cmd, shell=shell, env=env, close_fds=True,
80 stdin=stdin, stdout=stdout, stderr=stderr)
81 returncode = 0
82 except EnvironmentError as ex:
83 returncode = (ex.errno & 0xff)
84 if returncode == 0:
85 # This shouldn't happen, but just in case make sure the
86 # return code is never 0 here.
87 returncode = 255
88 except Exception:
89 returncode = 255
90 finally:
91 # mission accomplished, this child needs to exit and not
92 # continue the hg process here.
93 os._exit(returncode)
94
95 22 @contextlib.contextmanager
96 23 def flock(lockpath, description, timeout=-1):
97 24 """A flock based lock object. Currently it is always non-blocking.
@@ -50,7 +50,7 b' def backgroundrepack(repo, incremental=T'
50 50 if packsonly:
51 51 cmd.append('--packsonly')
52 52 repo.ui.warn(msg)
53 extutil.runbgcommand(cmd, encoding.environ)
53 procutil.runbgcommand(cmd, encoding.environ)
54 54
55 55 def fullrepack(repo, options=None):
56 56 """If ``packsonly`` is True, stores creating only loose objects are skipped.
@@ -25,7 +25,6 b' from . import ('
25 25 constants,
26 26 contentstore,
27 27 datapack,
28 extutil,
29 28 fileserverclient,
30 29 historypack,
31 30 metadatastore,
@@ -199,7 +198,7 b' def wraprepo(repo):'
199 198 cmd.append('--repack')
200 199 if revs:
201 200 cmd += ['-r', revs]
202 extutil.runbgcommand(cmd, encoding.environ)
201 procutil.runbgcommand(cmd, encoding.environ)
203 202
204 203 def prefetch(self, revs, base=None, pats=None, opts=None):
205 204 """Prefetches all the necessary file revisions for the given revs
@@ -10,6 +10,7 b''
10 10 from __future__ import absolute_import
11 11
12 12 import contextlib
13 import errno
13 14 import imp
14 15 import io
15 16 import os
@@ -467,3 +468,74 b' def uninterruptable(warn):'
467 468 signal.signal(signal.SIGINT, oldsiginthandler[0])
468 469 if shouldbail:
469 470 raise KeyboardInterrupt
471
472 if pycompat.iswindows:
473 # no fork on Windows, but we can create a detached process
474 # https://msdn.microsoft.com/en-us/library/windows/desktop/ms684863.aspx
475 # No stdlib constant exists for this value
476 DETACHED_PROCESS = 0x00000008
477 _creationflags = DETACHED_PROCESS | subprocess.CREATE_NEW_PROCESS_GROUP
478
479 def runbgcommand(script, env, shell=False, stdout=None, stderr=None):
480 '''Spawn a command without waiting for it to finish.'''
481 # we can't use close_fds *and* redirect stdin. I'm not sure that we
482 # need to because the detached process has no console connection.
483 subprocess.Popen(
484 script, shell=shell, env=env, close_fds=True,
485 creationflags=_creationflags, stdout=stdout, stderr=stderr)
486 else:
487 def runbgcommand(cmd, env, shell=False, stdout=None, stderr=None):
488 '''Spawn a command without waiting for it to finish.'''
489 # double-fork to completely detach from the parent process
490 # based on http://code.activestate.com/recipes/278731
491 pid = os.fork()
492 if pid:
493 # Parent process
494 (_pid, status) = os.waitpid(pid, 0)
495 if os.WIFEXITED(status):
496 returncode = os.WEXITSTATUS(status)
497 else:
498 returncode = -os.WTERMSIG(status)
499 if returncode != 0:
500 # The child process's return code is 0 on success, an errno
501 # value on failure, or 255 if we don't have a valid errno
502 # value.
503 #
504 # (It would be slightly nicer to return the full exception info
505 # over a pipe as the subprocess module does. For now it
506 # doesn't seem worth adding that complexity here, though.)
507 if returncode == 255:
508 returncode = errno.EINVAL
509 raise OSError(returncode, 'error running %r: %s' %
510 (cmd, os.strerror(returncode)))
511 return
512
513 returncode = 255
514 try:
515 # Start a new session
516 os.setsid()
517
518 stdin = open(os.devnull, 'r')
519 if stdout is None:
520 stdout = open(os.devnull, 'w')
521 if stderr is None:
522 stderr = open(os.devnull, 'w')
523
524 # connect stdin to devnull to make sure the subprocess can't
525 # muck up that stream for mercurial.
526 subprocess.Popen(
527 cmd, shell=shell, env=env, close_fds=True,
528 stdin=stdin, stdout=stdout, stderr=stderr)
529 returncode = 0
530 except EnvironmentError as ex:
531 returncode = (ex.errno & 0xff)
532 if returncode == 0:
533 # This shouldn't happen, but just in case make sure the
534 # return code is never 0 here.
535 returncode = 255
536 except Exception:
537 returncode = 255
538 finally:
539 # mission accomplished, this child needs to exit and not
540 # continue the hg process here.
541 os._exit(returncode)
General Comments 0
You need to be logged in to leave comments. Login now