),
user=user if not scope else None,
group=group if not scope else None,
- foreground=False,
) as proc: # fmt: skip
yield
proc.terminate()
services = json.loads(
run(
["busctl", "list", "--json=pretty"],
- foreground=False,
env=os.environ | config.environment,
sandbox=config.sandbox(relaxed=True),
stdout=subprocess.PIPE,
}
),
],
- foreground=False,
env=os.environ | config.environment,
sandbox=config.sandbox(relaxed=True),
# Make sure varlinkctl doesn't write to stdout which messes up the terminal.
str(pid),
fname if fname.is_dir() else "",
], # fmt: skip
- foreground=False,
env=os.environ | config.environment,
sandbox=config.sandbox(relaxed=True),
# systemd-machined might not be installed so let's ignore any failures unless running in debug
stderr=stderr,
pass_fds=qemu_device_fds.values(),
env=os.environ | config.environment,
- foreground=True,
sandbox=config.sandbox(
network=True,
devices=True,
Popen = subprocess.Popen
-def make_foreground_process(*, new_process_group: bool = True) -> None:
- """
- If we're connected to a terminal, put the process in a new process group and make that the foreground
- process group so that only this process receives SIGINT.
- """
- STDERR_FILENO = 2
- if os.isatty(STDERR_FILENO):
- if new_process_group:
- os.setpgrp()
- old = signal.signal(signal.SIGTTOU, signal.SIG_IGN)
- try:
- os.tcsetpgrp(STDERR_FILENO, os.getpgrp())
- except OSError as e:
- if e.errno != errno.ENOTTY:
- raise e
- signal.signal(signal.SIGTTOU, old)
-
-
def ensure_exc_info() -> tuple[type[BaseException], BaseException, TracebackType]:
exctype, exc, tb = sys.exc_info()
assert exctype
pid = os.fork()
if pid == 0:
with uncaught_exception_handler(exit=os._exit):
- make_foreground_process()
target(*args, **kwargs)
try:
_, status = os.waitpid(pid, 0)
+ except KeyboardInterrupt:
+ os.kill(pid, signal.SIGINT)
+ _, status = os.waitpid(pid, 0)
except BaseException:
os.kill(pid, signal.SIGTERM)
_, status = os.waitpid(pid, 0)
- finally:
- make_foreground_process(new_process_group=False)
rc = os.waitstatus_to_exitcode(status)
group: Optional[int] = None,
env: Mapping[str, str] = {},
log: bool = True,
- foreground: bool = True,
success_exit_status: Sequence[int] = (0,),
sandbox: AbstractContextManager[Sequence[PathString]] = contextlib.nullcontext([]),
) -> CompletedProcess:
group=group,
env=env,
log=log,
- foreground=foreground,
success_exit_status=success_exit_status,
sandbox=sandbox,
) as process:
def preexec(
*,
- foreground: bool,
preexec_fn: Optional[Callable[[], None]],
pass_fds: Collection[int],
) -> None:
- if foreground:
- make_foreground_process()
if preexec_fn:
preexec_fn()
pass_fds: Collection[int] = (),
env: Mapping[str, str] = {},
log: bool = True,
- foreground: bool = False,
preexec_fn: Optional[Callable[[], None]] = None,
success_exit_status: Sequence[int] = (0,),
sandbox: AbstractContextManager[Sequence[PathString]] = contextlib.nullcontext([]),
# transformation in preexec().
pass_fds=[SD_LISTEN_FDS_START + i for i in range(len(pass_fds))],
env=env,
- preexec_fn=functools.partial(
- preexec,
- foreground=foreground,
- preexec_fn=preexec_fn,
- pass_fds=pass_fds,
- ),
+ preexec_fn=functools.partial(preexec, preexec_fn=preexec_fn, pass_fds=pass_fds),
) as proc:
if pwfd is not None:
os.close(pwfd)
# exception later on so it's not a problem that we don't yield at all.
if not failed():
yield proc
+ except KeyboardInterrupt:
+ proc.send_signal(signal.SIGINT)
+ raise
except BaseException:
proc.terminate()
raise
user=user,
group=group,
env=env,
- preexec_fn=functools.partial(
- preexec,
- foreground=True,
- preexec_fn=preexec_fn,
- pass_fds=tuple(),
- ),
+ preexec_fn=functools.partial(preexec, preexec_fn=preexec_fn, pass_fds=tuple()),
)
raise subprocess.CalledProcessError(returncode, cmdline)
except FileNotFoundError as e:
die(f"{e.filename} not found.")
- finally:
- if foreground:
- make_foreground_process(new_process_group=False)
def finalize_path(