diff options
author | jilles <jilles@FreeBSD.org> | 2014-03-15 14:58:48 +0000 |
---|---|---|
committer | jilles <jilles@FreeBSD.org> | 2014-03-15 14:58:48 +0000 |
commit | 94dae0aff1dddebb566cf2f69548fd9f50be8c78 (patch) | |
tree | f8932801a36ad6f4a3bffeaa6e0fb25e14c758c1 | |
parent | ad4ea38baed6b320d50d678342cee3364eaf6692 (diff) | |
download | FreeBSD-src-94dae0aff1dddebb566cf2f69548fd9f50be8c78.zip FreeBSD-src-94dae0aff1dddebb566cf2f69548fd9f50be8c78.tar.gz |
sh: Allow kill %job on jobs started without job control.
When killing a %job started without job control, kill all processes in it.
As with process groups and zombies, if any process in the job can be killed
or has already terminated, the command is successful.
This also fixes occasional failures of the builtins/kill1.0 test.
-rw-r--r-- | bin/kill/kill.c | 17 | ||||
-rw-r--r-- | bin/sh/bltin/bltin.h | 2 | ||||
-rw-r--r-- | bin/sh/jobs.c | 19 | ||||
-rw-r--r-- | bin/sh/tests/builtins/Makefile | 2 | ||||
-rw-r--r-- | bin/sh/tests/builtins/kill2.0 | 7 |
5 files changed, 30 insertions, 17 deletions
diff --git a/bin/kill/kill.c b/bin/kill/kill.c index ab1701e..b23c00a 100644 --- a/bin/kill/kill.c +++ b/bin/kill/kill.c @@ -67,7 +67,7 @@ static void usage(void); int main(int argc, char *argv[]) { - int errors, numsig, pid; + int errors, numsig, pid, ret; char *ep; if (argc < 2) @@ -133,22 +133,17 @@ main(int argc, char *argv[]) for (errors = 0; argc; argc--, argv++) { #ifdef SHELL - if (**argv == '%') { - pid = getjobpgrp(*argv); - /* - * Silently ignore terminated jobs, like the kernel - * silently ignores zombies. - */ - if (pid == 0) - continue; - } else + if (**argv == '%') + ret = killjob(*argv, numsig); + else #endif { pid = strtol(*argv, &ep, 10); if (!**argv || *ep) errx(2, "illegal process id: %s", *argv); + ret = kill(pid, numsig); } - if (kill(pid, numsig) == -1) { + if (ret == -1) { warn("%s", *argv); errors = 1; } diff --git a/bin/sh/bltin/bltin.h b/bin/sh/bltin/bltin.h index 0143b6e..bbf55f1 100644 --- a/bin/sh/bltin/bltin.h +++ b/bin/sh/bltin/bltin.h @@ -74,6 +74,6 @@ pointer stalloc(int); void error(const char *, ...) __printf0like(1, 2); -pid_t getjobpgrp(char *); +int killjob(const char *, int); extern char *commandname; diff --git a/bin/sh/jobs.c b/bin/sh/jobs.c index 9913a28..ae89671 100644 --- a/bin/sh/jobs.c +++ b/bin/sh/jobs.c @@ -95,9 +95,9 @@ static void restartjob(struct job *); #endif static void freejob(struct job *); static int waitcmdloop(struct job *); -pid_t getjobpgrp(char *); static struct job *getjob_nonotfound(const char *); static struct job *getjob(const char *); +pid_t killjob(const char *, int); static pid_t dowait(int, struct job *); static void checkzombies(void); static void cmdtxt(union node *); @@ -639,15 +639,26 @@ getjob(const char *name) } -pid_t -getjobpgrp(char *name) +int +killjob(const char *name, int sig) { struct job *jp; + int i, ret; jp = getjob(name); if (jp->state == JOBDONE) return 0; - return -jp->ps[0].pid; + if (jp->jobctl) + return kill(-jp->ps[0].pid, sig); + ret = -1; + errno = ESRCH; + for (i = 0; i < jp->nprocs; i++) + if (jp->ps[i].status == -1 || WIFSTOPPED(jp->ps[i].status)) { + if (kill(jp->ps[i].pid, sig) == 0) + ret = 0; + } else + ret = 0; + return ret; } /* diff --git a/bin/sh/tests/builtins/Makefile b/bin/sh/tests/builtins/Makefile index b76d631..945a14d 100644 --- a/bin/sh/tests/builtins/Makefile +++ b/bin/sh/tests/builtins/Makefile @@ -86,7 +86,7 @@ FILES+= hash3.0 hash3.0.stdout FILES+= hash4.0 FILES+= jobid1.0 FILES+= jobid2.0 -FILES+= kill1.0 +FILES+= kill1.0 kill2.0 FILES+= lineno.0 lineno.0.stdout FILES+= lineno2.0 FILES+= local1.0 diff --git a/bin/sh/tests/builtins/kill2.0 b/bin/sh/tests/builtins/kill2.0 new file mode 100644 index 0000000..31e0ba3 --- /dev/null +++ b/bin/sh/tests/builtins/kill2.0 @@ -0,0 +1,7 @@ +# $FreeBSD$ + +sleep 1 | sleep 1 & +kill %+ +wait "$!" +r=$? +[ "$r" -gt 128 ] && [ "$(kill -l "$r")" = TERM ] |