(patch at the end)

this happens when ksh isn't the process group leader

not being the group leader happens when, e.g., started as a background process
in a non interactive shell or being a rhs member of a pipe:

$ /bin/sh <<'.'
/bin/sh -c 'ps -opid,pgid -p$$' &
.
  PID  PGID
 5784  6401
$ : | /bin/sh -c 'ps -opid,pgid -p$$'
  PID  PGID
12208 20586

compile:

/* t.c BOF */
#include <sys/types.h>
#include <sys/wait.h>

#include <err.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int
main(int argc, char **argv)
{
        int gflag, s;
        char c;

        gflag = 0;
        while ((c = getopt(argc, argv, "g")) != -1)
                if (c == 'g')
                        gflag = 1;
                else
                        exit(2);
        argc -= optind;
        argv += optind;

        if (argc < 1)
                errx(2, "invalid arguments");

        switch (fork()) {
        case 0:
                if (gflag)
                        setpgid(0, 0);
                execv(*argv, argv);
                err(3, "exec: %s", *argv);
        case -1:
                err(3, "fork");
        }

        if (wait(&s) == -1)
                err(3, "wait");
        printf("eb=%d en=%d sb=%d sn=%d\n", WIFEXITED(s), WEXITSTATUS(s),
            WIFSIGNALED(s), WTERMSIG(s));
        
        exit(0);
}
/* t.c EOF */

all lines should produce the same output, but don't because of the bug:

$ {
./t    /bin/ksh -c 'kill -INT $$'
./t -g /bin/ksh -c 'kill -INT $$'
} | column -t
eb=1  en=130  sb=0  sn=0
eb=0  en=0    sb=1  sn=2

patch:

Index: main.c
===================================================================
RCS file: /cvs/src/bin/ksh/main.c,v
retrieving revision 1.47
diff -p -u -r1.47 main.c
--- main.c      7 Sep 2011 11:33:25 -0000       1.47
+++ main.c      10 Nov 2011 06:25:01 -0000
@@ -666,11 +666,11 @@ quitenv(struct shf *shf)
                                 * Don't do it for SIGQUIT, since we'd
                                 * dump a core..
                                 */
-                               if ((sig == SIGINT || sig == SIGTERM) &&
-                                   getpgrp() == kshpid) {
+                               if (sig == SIGINT || sig == SIGTERM) {
                                        setsig(&sigtraps[sig], SIG_DFL,
                                            SS_RESTORE_CURR|SS_FORCE);
-                                       kill(0, sig);
+                                       kill((getpgrp() == kshpid)
+                                           ? 0 : kshpid, sig);
                                }
                        }
                }

Reply via email to