aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJilles Tjoelker <jilles@FreeBSD.org>2014-03-15 14:58:48 +0000
committerJilles Tjoelker <jilles@FreeBSD.org>2014-03-15 14:58:48 +0000
commit76961687061bd93c0158c29f839c064613aee364 (patch)
treef8932801a36ad6f4a3bffeaa6e0fb25e14c758c1
parenta5bf6b6d215821f4317ab62aa4e8add5353a3fda (diff)
downloadsrc-76961687061bd93c0158c29f839c064613aee364.tar.gz
src-76961687061bd93c0158c29f839c064613aee364.zip
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.
Notes
Notes: svn path=/head/; revision=263206
-rw-r--r--bin/kill/kill.c17
-rw-r--r--bin/sh/bltin/bltin.h2
-rw-r--r--bin/sh/jobs.c19
-rw-r--r--bin/sh/tests/builtins/Makefile2
-rw-r--r--bin/sh/tests/builtins/kill2.07
5 files changed, 30 insertions, 17 deletions
diff --git a/bin/kill/kill.c b/bin/kill/kill.c
index ab1701e03bdb..b23c00acf21c 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 0143b6e27aca..bbf55f1ae79f 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 9913a289de1a..ae896711037e 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 b76d6312342a..945a14d6c518 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 000000000000..31e0ba362b80
--- /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 ]