uutils / coreutils

Cross-platform Rust rewrite of the GNU coreutils
https://uutils.github.io/
MIT License
17.56k stars 1.26k forks source link

kill: Don't error on signal 0 / SIGEXIT #6228

Closed BenWiederhake closed 4 months ago

BenWiederhake commented 5 months ago

It seems that we somehow try to kill with signal 0. This should instead be a no-op. On Linux we don't do any kill-ish syscall so I assume that somehow it's libc handling this case and returning EINVAL, I guess.

$ sleep 9999 &
[1] 1902887
$ ../gnu/src/kill -s EXIT 1902887  # does nothing, successfully
$ ../gnu/src/kill -s SIGEXIT 1902887  # does nothing, successfully
$ cargo run --features kill kill -s SIGEXIT 1902887  # does nothing, unsuccessfully
kill: Invalid input
[$? = 1]
$ cargo run --features kill kill -s EXIT 1902887  # does nothing, unsuccessfully
kill: Invalid input
[$? = 1]
$ ps # 'sleep' is still running!
    PID TTY          TIME CMD
1197972 pts/5    00:00:02 bash
1902887 pts/5    00:00:00 sleep
1903493 pts/5    00:00:00 ps
$ strace target/debug/coreutils kill -s EXIT 1902887 # There is no actual kill-syscall being made
// <SNIP a few lines that are clearly startup>
openat(AT_FDCWD, "/proc/self/maps", O_RDONLY|O_CLOEXEC) = 3
prlimit64(0, RLIMIT_STACK, NULL, {rlim_cur=8192*1024, rlim_max=RLIM64_INFINITY}) = 0
newfstatat(3, "", {st_mode=S_IFREG|0444, st_size=0, ...}, AT_EMPTY_PATH) = 0
read(3, "5565fe72c000-5565fe888000 r--p 0"..., 1024) = 1024
read(3, " /usr/lib/x86_64-linux-gnu/libc."..., 1024) = 1024
read(3, "       /usr/lib/x86_64-linux-gnu"..., 1024) = 1024
read(3, "      /usr/lib/x86_64-linux-gnu/"..., 1024) = 414
close(3)                                = 0
sched_getaffinity(1904028, 32, [0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15]) = 8
write(2, "kill", 4kill)                     = 4
write(2, ": ", 2: )                       = 2
write(2, "Invalid input", 13Invalid input)           = 13
<SNIP more lines that are clearly post-error>

Found while thinking about #6222.

EDIT: Note that GNU kill does the syscall, so it's probably not filtered/prevented by libc, I guess:

$ sleep 999 &
[1] 2063858
$ strace ../gnu/src/kill 2063858 -s SIGEXIT
<SNIP bootup and library reading>
getrandom("\x48\x2b\x82\xf2\x96\xa2\x48\x63", 8, GRND_NONBLOCK) = 8
brk(NULL)                               = 0x55cbc0dfb000
brk(0x55cbc0e1c000)                     = 0x55cbc0e1c000
kill(2063858, 0)                        = 0
close(1)                                = 0
close(2)                                = 0
exit_group(0)                           = ?
+++ exited with 0 +++
$ ps  # 'sleep' is still running
    PID TTY          TIME CMD
1197972 pts/5    00:00:02 bash
2063858 pts/5    00:00:00 sleep
2064245 pts/5    00:00:00 ps
$
dcarrier commented 5 months ago

Had some time to look into this a bit this afternoon and may have found something interesting.

Looks like the error is coming from this code path: https://github.com/uutils/coreutils/blob/d63bc4a4e1774fffc22b5d376eca9eb8e615057d/src/uu/kill/src/kill.rs#L63-L65

Which propagates to the user as kill: Invalid input that you noted above. I believe this is due to the fact that nix::Signal does not support SIGEXIT.

It looks like if signal: T ends up as None in the nix kill function then it will do what we want: link. Although I am not sure how to do that yet, bit of a rust noob :)

dcarrier commented 4 months ago

Mocked up a potential solution here.

If others agree I can clean this up a bit and submit a PR.

BenWiederhake commented 4 months ago

I don't fully understand the reasoning, because SIGPOLL is also missing from the list, but running it show that it is treated correctly.

Your code looks good, please create a PR and let's move the discussion there :)

BenWiederhake commented 4 months ago

Closed by #6269