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 |
|
|
|
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 |
|
|
|
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