(process_name, cmdline, env, redirect_output)
| 38 | |
| 39 | |
| 40 | def spawn(process_name, cmdline, env, redirect_output): |
| 41 | log.info( |
| 42 | "Spawning debuggee process:\n\n" |
| 43 | "Command line: {0!r}\n\n" |
| 44 | "Environment variables: {1!r}\n\n", |
| 45 | cmdline, |
| 46 | env, |
| 47 | ) |
| 48 | |
| 49 | close_fds = set() |
| 50 | try: |
| 51 | if redirect_output: |
| 52 | # subprocess.PIPE behavior can vary substantially depending on Python version |
| 53 | # and platform; using our own pipes keeps it simple, predictable, and fast. |
| 54 | stdout_r, stdout_w = os.pipe() |
| 55 | stderr_r, stderr_w = os.pipe() |
| 56 | close_fds |= {stdout_r, stdout_w, stderr_r, stderr_w} |
| 57 | kwargs = dict(stdout=stdout_w, stderr=stderr_w) |
| 58 | else: |
| 59 | kwargs = {} |
| 60 | |
| 61 | if sys.platform != "win32" and sys.implementation.name != 'graalpy': |
| 62 | # GraalPy does not support running code between fork and exec |
| 63 | |
| 64 | def preexec_fn(): |
| 65 | try: |
| 66 | # Start the debuggee in a new process group, so that the launcher can |
| 67 | # kill the entire process tree later. |
| 68 | os.setpgrp() |
| 69 | |
| 70 | # Make the new process group the foreground group in its session, so |
| 71 | # that it can interact with the terminal. The debuggee will receive |
| 72 | # SIGTTOU when tcsetpgrp() is called, and must ignore it. |
| 73 | old_handler = signal.signal(signal.SIGTTOU, signal.SIG_IGN) |
| 74 | try: |
| 75 | tty = os.open("/dev/tty", os.O_RDWR) |
| 76 | try: |
| 77 | os.tcsetpgrp(tty, os.getpgrp()) |
| 78 | finally: |
| 79 | os.close(tty) |
| 80 | finally: |
| 81 | signal.signal(signal.SIGTTOU, old_handler) |
| 82 | except Exception: |
| 83 | # Not an error - /dev/tty doesn't work when there's no terminal. |
| 84 | log.swallow_exception( |
| 85 | "Failed to set up process group", level="info" |
| 86 | ) |
| 87 | |
| 88 | kwargs.update(preexec_fn=preexec_fn) |
| 89 | |
| 90 | try: |
| 91 | global process |
| 92 | process = subprocess.Popen(cmdline, env=env, bufsize=0, **kwargs) |
| 93 | except Exception as exc: |
| 94 | raise messaging.MessageHandlingError( |
| 95 | "Couldn't spawn debuggee: {0}\n\nCommand line:{1!r}".format( |
| 96 | exc, cmdline |
| 97 | ) |
nothing calls this directly
no test coverage detected
searching dependent graphs…