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.
This commit is contained in:
jilles 2014-03-15 14:58:48 +00:00
parent ad4ea38bae
commit 94dae0aff1
5 changed files with 30 additions and 17 deletions

View File

@ -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;
}

View File

@ -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;

View File

@ -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;
}
/*

View File

@ -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

View File

@ -0,0 +1,7 @@
# $FreeBSD$
sleep 1 | sleep 1 &
kill %+
wait "$!"
r=$?
[ "$r" -gt 128 ] && [ "$(kill -l "$r")" = TERM ]