From cb5d8bfe8621c8029f97647ec543ce6e7c41fa58 Mon Sep 17 00:00:00 2001 From: Chris Down Date: Mon, 17 Feb 2020 10:11:46 -0500 Subject: 45451: builtins: kill: Add basic test suite This is not totally comprehensive, but at least it's a start for the core functionality. In the next commits, we'll also use this base to add some regression tests. --- Test/B11kill.ztst | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 Test/B11kill.ztst (limited to 'Test/B11kill.ztst') diff --git a/Test/B11kill.ztst b/Test/B11kill.ztst new file mode 100644 index 000000000..26d7a11fe --- /dev/null +++ b/Test/B11kill.ztst @@ -0,0 +1,60 @@ +# Tests for the kill builtin. +# +# The exit codes 11 and 19 in this file don't mean anything special; they're +# just exit codes which are specific enough that the failure of `kill` itself +# can be differentiated from exiting due to executing a trap. + +%test + +# Correct invocation + + if zmodload zsh/system &>/dev/null; then + ( + trap 'exit 19' TERM + kill $sysparams[pid] + ) + else + ZTST_skip='Cannot zmodload zsh/system, skipping kill with no sigspec' + fi +19:kill with no sigspec + + + if zmodload zsh/system &>/dev/null; then + ( + trap 'exit 11' USR1 + kill -USR1 $sysparams[pid] + ) + else + ZTST_skip='Cannot zmodload zsh/system, skipping kill with sigspec' + fi +11:kill with sigspec + +# Incorrect invocation + + ( + kill a b c + ) +3:kill with multiple wrong inputs should increment status +?(eval):kill:2: illegal pid: a +?(eval):kill:2: illegal pid: b +?(eval):kill:2: illegal pid: c + + ( + kill -INT a b c + ) +3:kill with sigspec and wrong inputs should increment status +?(eval):kill:2: illegal pid: a +?(eval):kill:2: illegal pid: b +?(eval):kill:2: illegal pid: c + + ( + kill + ) +1:kill with no arguments +?(eval):kill:2: not enough arguments + + ( + kill -INT + ) +1:kill with sigspec only +?(eval):kill:2: not enough arguments -- cgit 1.4.1 From 59258252b501159c2988de3a2d87a18dc17e98b1 Mon Sep 17 00:00:00 2001 From: Chris Down Date: Mon, 17 Feb 2020 10:12:02 -0500 Subject: 45452: builtins: kill: Add `kill ''` regression test with explicit sigspec The version without a sigspec can't be added yet because it would still kill the test runner even in expected-to-fail mode; see workers/45449 for discussion. For the same reason, we use a signal which is non-fatal by default and unlikely to be sent by someone else, SIGURG, to do the expected-to-fail case prior to the fix. --- ChangeLog | 3 +++ Test/B11kill.ztst | 9 +++++++++ 2 files changed, 12 insertions(+) (limited to 'Test/B11kill.ztst') diff --git a/ChangeLog b/ChangeLog index 4d48d787c..162bde6b0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2020-02-18 Chris Down + * 45452: Test/B11kill.ztst: builtins: kill: Add `kill ''` + regression test with explicit sigspec + * 45451: Test/B11kill.ztst: builtins: kill: Add basic test suite 2020-02-17 brian m. carlson diff --git a/Test/B11kill.ztst b/Test/B11kill.ztst index 26d7a11fe..957a7b385 100644 --- a/Test/B11kill.ztst +++ b/Test/B11kill.ztst @@ -58,3 +58,12 @@ ) 1:kill with sigspec only ?(eval):kill:2: not enough arguments + +# Regression tests: `kill ''` should not result in `kill 0`. + + ( + trap 'exit 11' URG + kill -URG '' + ) +1f:kill with empty pid and sigspec should not send signal to current process group +?(eval):kill:3: illegal pid: -- cgit 1.4.1 From 5c55b3fb50bbfe602fcfa55fa6258e398ecc6b20 Mon Sep 17 00:00:00 2001 From: Chris Down Date: Mon, 17 Feb 2020 10:12:11 -0500 Subject: 45453: builtins: kill: Do not signal current process group when pid is empty The following case was encountered in the wild: % zsh; echo "$?" % trap 'exit 5' TERM % kill '' 5 This behaviour seems more likely to be the result of bugs in programs (e.g. `kill -9 "$unsetvar") rather than being desirable behaviour to me. It also seems unintentional judging by the code and documentation, since it comes about as a result of the fact that: - `isanum` returns true for empty strings (since an empty string technically only consists of digits and minuses...); - `atoi`, when passed a pointer to an invalid number, returns 0; - `kill(0, signal)` sends the signal in question to all processes in the current process group. There are (at least) two ways to solve this issue: 1. Add special handling to `kill` to avoid this case. See this patch[0] for a version that does that. 2. Change how isanum behaves. Since the only two call sites that use it both seem like they should handle the case where the input char array is empty, that seems like a reasonable overall change to me.[1] After this patch: % trap 'exit 5' TERM % kill '' kill: illegal pid: The regression test for `kill` without a sigspec is also included in this commit, as previously it's not possible to test it trivially as it would still kill the test runner in expected-to-fail mode; see discussion in workers/45449. 0: workers/45426: https://www.zsh.org/mla/workers/2020/msg00251.html 1: The other call site using isanum() is the fg builtin, but in that case we just fail later since we can't find any job named '', so no big deal either way. It's the kill case which is more concerning. --- ChangeLog | 3 +++ Src/jobs.c | 5 +++-- Test/B11kill.ztst | 10 +++++++++- 3 files changed, 15 insertions(+), 3 deletions(-) (limited to 'Test/B11kill.ztst') diff --git a/ChangeLog b/ChangeLog index 162bde6b0..9a7ca36a0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2020-02-18 Chris Down + * 45453: Src/jobs.c, Test/B11kill.ztst: builtins: kill: Do not + signal current process group when pid is empty + * 45452: Test/B11kill.ztst: builtins: kill: Add `kill ''` regression test with explicit sigspec diff --git a/Src/jobs.c b/Src/jobs.c index e7438251e..0485f2c7c 100644 --- a/Src/jobs.c +++ b/Src/jobs.c @@ -1854,13 +1854,14 @@ scanjobs(void) /* This simple function indicates whether or not s may represent * * a number. It returns true iff s consists purely of digits and * - * minuses. Note that minus may appear more than once, and the empty * - * string will produce a `true' response. */ + * minuses. Note that minus may appear more than once. */ /**/ static int isanum(char *s) { + if (*s == '\0') + return 0; while (*s == '-' || idigit(*s)) s++; return *s == '\0'; diff --git a/Test/B11kill.ztst b/Test/B11kill.ztst index 957a7b385..40dd99cd3 100644 --- a/Test/B11kill.ztst +++ b/Test/B11kill.ztst @@ -65,5 +65,13 @@ trap 'exit 11' URG kill -URG '' ) -1f:kill with empty pid and sigspec should not send signal to current process group +1:kill with empty pid and sigspec should not send signal to current process group ?(eval):kill:3: illegal pid: + + ( + trap 'exit 19' TERM + kill '' + ) +1:Plain kill with empty pid should not send signal to current process group +?(eval):kill:3: illegal pid: + -- cgit 1.4.1 From 69c247de2ff3ca41be93cd90af539926418d023d Mon Sep 17 00:00:00 2001 From: Chris Down Date: Tue, 18 Feb 2020 13:54:37 -0500 Subject: 45463: test: kill: Document why we use SIGURG See discussion in workers/45460. --- ChangeLog | 3 +++ Test/B11kill.ztst | 9 +++++++++ 2 files changed, 12 insertions(+) (limited to 'Test/B11kill.ztst') diff --git a/ChangeLog b/ChangeLog index 9a7ca36a0..5fabad45c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2020-02-18 Chris Down + * 45463: Test/B11kill.ztst: test: kill: Document why we use + SIGURG + * 45453: Src/jobs.c, Test/B11kill.ztst: builtins: kill: Do not signal current process group when pid is empty diff --git a/Test/B11kill.ztst b/Test/B11kill.ztst index 40dd99cd3..dc6bf9b89 100644 --- a/Test/B11kill.ztst +++ b/Test/B11kill.ztst @@ -60,6 +60,15 @@ ?(eval):kill:2: not enough arguments # Regression tests: `kill ''` should not result in `kill 0`. +# +# We use SIGURG where an explicit sigspec can be provided as: +# +# 1. By default it's non-terminal, so even if we regress, we won't kill the +# test runner and other processes in the process group since we'll stop +# running this test before we get to the plain kill (and thus SIGTERM) +# cases; +# 2. It's also unlikely to be sent for any other reason during the process +# lifetime, so the test shouldn't be flaky. ( trap 'exit 11' URG -- cgit 1.4.1