Show More
@@ -701,7 +701,88 b' if pycompat.iswindows:' | |||
|
701 | 701 | |
|
702 | 702 | else: |
|
703 | 703 | |
|
704 | def runbgcommand( | |
|
704 | def runbgcommandpy3( | |
|
705 | cmd, | |
|
706 | env, | |
|
707 | shell=False, | |
|
708 | stdout=None, | |
|
709 | stderr=None, | |
|
710 | ensurestart=True, | |
|
711 | record_wait=None, | |
|
712 | stdin_bytes=None, | |
|
713 | ): | |
|
714 | """Spawn a command without waiting for it to finish. | |
|
715 | ||
|
716 | ||
|
717 | When `record_wait` is not None, the spawned process will not be fully | |
|
718 | detached and the `record_wait` argument will be called with a the | |
|
719 | `Subprocess.wait` function for the spawned process. This is mostly | |
|
720 | useful for developers that need to make sure the spawned process | |
|
721 | finished before a certain point. (eg: writing test)""" | |
|
722 | if pycompat.isdarwin: | |
|
723 | # avoid crash in CoreFoundation in case another thread | |
|
724 | # calls gui() while we're calling fork(). | |
|
725 | gui() | |
|
726 | ||
|
727 | if shell: | |
|
728 | script = cmd | |
|
729 | else: | |
|
730 | if isinstance(cmd, bytes): | |
|
731 | cmd = [cmd] | |
|
732 | script = b' '.join(shellquote(x) for x in cmd) | |
|
733 | if record_wait is None: | |
|
734 | # double-fork to completely detach from the parent process | |
|
735 | script = b'( %s ) &' % script | |
|
736 | start_new_session = True | |
|
737 | else: | |
|
738 | start_new_session = False | |
|
739 | ensurestart = True | |
|
740 | ||
|
741 | try: | |
|
742 | if stdin_bytes is None: | |
|
743 | stdin = subprocess.DEVNULL | |
|
744 | else: | |
|
745 | stdin = pycompat.unnamedtempfile() | |
|
746 | stdin.write(stdin_bytes) | |
|
747 | stdin.flush() | |
|
748 | stdin.seek(0) | |
|
749 | if stdout is None: | |
|
750 | stdout = subprocess.DEVNULL | |
|
751 | if stderr is None: | |
|
752 | stderr = subprocess.DEVNULL | |
|
753 | ||
|
754 | p = subprocess.Popen( | |
|
755 | script, | |
|
756 | shell=True, | |
|
757 | env=env, | |
|
758 | close_fds=True, | |
|
759 | stdin=stdin, | |
|
760 | stdout=stdout, | |
|
761 | stderr=stderr, | |
|
762 | start_new_session=start_new_session, | |
|
763 | ) | |
|
764 | except Exception: | |
|
765 | if record_wait is not None: | |
|
766 | record_wait(255) | |
|
767 | raise | |
|
768 | finally: | |
|
769 | if stdin_bytes is not None: | |
|
770 | stdin.close() | |
|
771 | if not ensurestart: | |
|
772 | # Even though we're not waiting on the child process, | |
|
773 | # we still must call waitpid() on it at some point so | |
|
774 | # it's not a zombie/defunct. This is especially relevant for | |
|
775 | # chg since the parent process won't die anytime soon. | |
|
776 | # We use a thread to make the overhead tiny. | |
|
777 | t = threading.Thread(target=lambda: p.wait) | |
|
778 | t.daemon = True | |
|
779 | t.start() | |
|
780 | else: | |
|
781 | returncode = p.wait | |
|
782 | if record_wait is not None: | |
|
783 | record_wait(returncode) | |
|
784 | ||
|
785 | def runbgcommandpy2( | |
|
705 | 786 | cmd, |
|
706 | 787 | env, |
|
707 | 788 | shell=False, |
@@ -811,3 +892,14 b' else:' | |||
|
811 | 892 | stdin.close() |
|
812 | 893 | if record_wait is None: |
|
813 | 894 | os._exit(returncode) |
|
895 | ||
|
896 | if pycompat.ispy3: | |
|
897 | # This branch is more robust, because it avoids running python | |
|
898 | # code (hence gc finalizers, like sshpeer.__del__, which | |
|
899 | # blocks). But we can't easily do the equivalent in py2, | |
|
900 | # because of the lack of start_new_session=True flag. Given | |
|
901 | # that the py2 branch should die soon, the short-lived | |
|
902 | # duplication seems acceptable. | |
|
903 | runbgcommand = runbgcommandpy3 | |
|
904 | else: | |
|
905 | runbgcommand = runbgcommandpy2 |
General Comments 0
You need to be logged in to leave comments.
Login now