| 330 | } |
| 331 | |
| 332 | static int spawn_ignoring_tree(const char *pid_path, int quiet_timeout_ms, int cancel_grace_ms, |
| 333 | cbm_subprocess_t **out) { |
| 334 | /* The direct child installs its trap before starting a nested shell. The two |
| 335 | * PIDs are written only after the nested process exists, eliminating the |
| 336 | * cancellation-before-trap race from the test. */ |
| 337 | const char *script = "trap '' TERM; " |
| 338 | "/bin/sh -c 'trap \"\" TERM; while :; do sleep 1; done' cbm-grandchild & " |
| 339 | "grandchild=$!; echo \"$$ $grandchild\" > \"$1\"; wait"; |
| 340 | const char *argv[] = {"/bin/sh", "-c", script, "cbm-parent", pid_path, NULL}; |
| 341 | cbm_proc_opts_t opts = {0}; |
| 342 | opts.bin = "/bin/sh"; |
| 343 | opts.argv = argv; |
| 344 | opts.quiet_timeout_ms = quiet_timeout_ms; |
| 345 | opts.cancel_grace_ms = cancel_grace_ms; |
| 346 | return cbm_subprocess_spawn(&opts, out); |
| 347 | } |
| 348 | |
| 349 | typedef struct { |
| 350 | cbm_subprocess_t *process; |
no test coverage detected