equal
deleted
inserted
replaced
14 import io |
14 import io |
15 import os |
15 import os |
16 import signal |
16 import signal |
17 import subprocess |
17 import subprocess |
18 import sys |
18 import sys |
|
19 import threading |
19 import time |
20 import time |
20 |
21 |
21 from ..i18n import _ |
22 from ..i18n import _ |
22 from ..pycompat import ( |
23 from ..pycompat import ( |
23 getattr, |
24 getattr, |
602 # based on http://code.activestate.com/recipes/278731 |
603 # based on http://code.activestate.com/recipes/278731 |
603 if record_wait is None: |
604 if record_wait is None: |
604 pid = os.fork() |
605 pid = os.fork() |
605 if pid: |
606 if pid: |
606 if not ensurestart: |
607 if not ensurestart: |
|
608 # Even though we're not waiting on the child process, |
|
609 # we still must call waitpid() on it at some point so |
|
610 # it's not a zombie/defunct. This is especially relevant for |
|
611 # chg since the parent process won't die anytime soon. |
|
612 # We use a thread to make the overhead tiny. |
|
613 def _do_wait(): |
|
614 os.waitpid(pid, 0) |
|
615 threading.Thread(target=_do_wait, daemon=True).start() |
607 return |
616 return |
608 # Parent process |
617 # Parent process |
609 (_pid, status) = os.waitpid(pid, 0) |
618 (_pid, status) = os.waitpid(pid, 0) |
610 if os.WIFEXITED(status): |
619 if os.WIFEXITED(status): |
611 returncode = os.WEXITSTATUS(status) |
620 returncode = os.WEXITSTATUS(status) |