Subject: bug#76282: Signal handling (like SIGINT) and guix shell --container: PID 1

From: Maxim Cournoyer <[email-masked]>
Date: Sat, 31 May 2025 23:50:13 +0900

Hi,

[email-masked] writes:

> # 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>`)

[...]

Thank you for the detailed investigation!  I just encountered this
behavior attempting to build forgejo in a containerized environment,
using the following manifest.scm file:

```
(specifications->manifest
 (list "coreutils"
       "findutils"
       "gcc-toolchain"
       "git-minimal"
       "go"
       "grep"
       "make"
       "node"
       "nss-certs"
       "sed"))
```

The problem curiously only occurs when '--' is used to launch the
application; otherwise it works normally, e.g.:

--8<---------------cut here---------------start------------->8---
$ guix shell -CNF -m manifest.scm
[env]$ env GOPATH=/tmp TAGS="bindata timetzdata sqlite sqlite_unlock_notify" make build
go: downloading go1.24.3 (linux/amd64)
^C
[env]$ # aborted correctly
--8<---------------cut here---------------end--------------->8---

Your analysis appears correct; the above 'make' runs with PID 3.

--8<---------------cut here---------------start------------->8---
maxim@terra ~/src/forgejo$ guix shell -CNF -m manifest.scm -- env GOPATH=/tmp TAGS="bindata timetzdata sqlite sqlite_unlock_notify" make build
go: downloading go1.24.3 (linux/amd64)
^Cgo: downloading go1.24.3 (linux/amd64)
^Cgo: downloading go1.24.3 (linux/amd64)
^Cgo: downloading go1.24.3 (linux/amd64)
^Cgo: downloading go1.24.3 (linux/amd64)
^CForgejo requires Go 1.24 or greater to build. You can get it at https://go.dev/dl/
make: *** [Makefile:297: go-check] Error 1
^C^C^C^C^C^C^C^C^C
# doesn't abort, need kill -9 $pid
--8<---------------cut here---------------end--------------->8---

This doesn't handle signals as expected because it runs as PID 1.  I
agree this needs be documented or better, handled with --init ala
docker.

-- 
Thanks,
Maxim