deno_task_shell icon indicating copy to clipboard operation
deno_task_shell copied to clipboard

feat: add ProcessSignaler to expose child process PIDs

Open wolfv opened this issue 1 month ago • 5 comments

Add ProcessSignaler type to track spawned child process PIDs, enabling proper signal forwarding by allowing callers to check process groups before forwarding signals.

  • Add ProcessSignaler with current_pid() and subscribe() methods
  • Add execute_with_signaler() convenience function
  • Add ShellState::new_with_process_signaler() constructor
  • Notify on process spawn/exit in ExecutableCommand

wolfv avatar Nov 28 '25 19:11 wolfv

Add ProcessSignaler type to track spawned child process PIDs, enabling proper signal forwarding by allowing callers to check process groups before forwarding signals.

I'm a little confused about this PR. Is this a replacement for KillSignal? Can you explain it a little more and show a use case? I'm not that familiar with process groups and when a spawned process would end up in a different process group (how could that happen?). Thanks!

dsherret avatar Nov 28 '25 20:11 dsherret

Hey @dsherret to be completely transparent the changes here were written by Claude :) I didn't expect you to already take a look tbh.

I am trying to fix an issue in Pixi where a user has issues to programmatically send CTRL+C to the process.

ProcessSignaler is complementary to KillSignal, not a replacement.

  • KillSignal is for sending signals to child processes (pixi → child)
  • ProcessSignaler is for observing child process PIDs so the caller can make decisions about signal forwarding

The Problem: When you run pixi run python script.py in a terminal and press CTRL+C:

The terminal sends SIGINT to the entire foreground process group

  • Both pixi AND the python child receive SIGINT directly from the terminal
  • But when you run kill -INT <pixi_pid> from another terminal or a job scheduler (like SLURM):
    • Only pixi receives SIGINT
    • The child never gets the signal unless pixi forwards it

The challenge is: pixi needs to forward signals sent via kill, but should avoid double-forwarding when CTRL+C already delivered the signal to the child.

When would a child be in a different process group?

By default, child processes inherit the parent's process group. But processes can call setpgid() or setsid() to create a new process group. This happens with:

  • Daemons/background services
  • Some shell commands that manage their own process groups
  • Programs using job control

wolfv avatar Nov 28 '25 20:11 wolfv

Here is an explanation in uv about the same issue: https://github.com/astral-sh/uv/blob/5f3d46c2413225aac68c86fa24be97c4c2c193e4/crates/uv/src/child.rs#L12-L24

How are you solving this in deno? :)

wolfv avatar Nov 28 '25 20:11 wolfv

Thanks! It seems a bit complicated to introduce a separate concept for this. Is there a way we could build this into KillSignal instead? For example, a way to say "send this signal only if a different process group".

dsherret avatar Nov 28 '25 21:11 dsherret

I still need to test in pixi whether this fixes our CTRL+C / kill signal issues. Marked the PR as draft.

wolfv avatar Nov 29 '25 08:11 wolfv