# Bug and reproducer There is a discrepancy between (expected) signal handling of programs when running them directly, vs. using `guix shell --container -- program`.
An example program can be used to illustrate: ``` ; test.scm ; Test guix shell to catch ctrl-C signal (while #t (display "In infinite loop...\n") (sleep 1)) ``` It uses guile, since bash does some extra funky signal-related things, which not every program does. My usecase is `typst watch`, a program which only exits on ctrl-C, else it loops. 1) Run as `guile test.scm` and use ctrl-C It terminates as expected. Same when using `guix shell --container guile` and then `guile test.scm` inside the container shell. 2) Run `guix shell --container guile -- guile test.scm` and use ctrl-C It doesn't terminate as expected. Only method is to get the PID and use SIGKILL (`kill -KILL <pid>`) # Reason (as far as I know): `guix shell --container -- program` starts the program with PID 1 in it's dedicated namespace. However, PID 1 is handled specially by the kernel when it comes to signal handlers. Only explicitly registered handlers are used and the default handlers are not executed for PID 1 (except SIGKILL & SIGSTOP). You can use `cat /proc/<PID in parent namespace>/status | grep ^NStgid` to verify the PID seen by the process (rightmost number). # Sources: - https://lwn.net/Articles/532748/ ("Signals and the init process") - In docker: https://ddanilov.me/how-signals-are-handled-in-a-docker-container - Docker '--init' flag: https://docs.docker.com/reference/cli/docker/container/run/#init - bash doing funky things: https://colinxy.github.io/computer-science/2017/01/27/bash-handles-signals.html - Check namespace PID: https://unix.stackexchange.com/questions/625520/is-it-possible-to-check-the-process-id-of-child-in-different-pid-namespace # Possible fixes: - Document the behaviour (and nothing more?) This is the minimum, and I'll see if I can send a patch. This lengthy bugreport is due to undocumented & unexpected behaviour, leading down a rabbit hole ;) - Add an `--init` argument, like in docker? This adds some minimal init process to forward signals and reap processes... Not sure how minimal the shepherd is? - Do this by default, and add a --no-init argument? - ... # Workaround: Add "tini" or "catatonit" as a minimal PID 1 process. - guix shell --container guile tini -- tini guile test.scm - guix shell --container guile catatonit -- catatonit guile test.scm Best regards, Ingar