Hi *,

since this topic often occurs, not the least when porting to
Syllable, Plan 9, Linux/µclibc-ng/nios2, etc. here’s a patch
relative to mksh R52c (last formal release), enabling a num‐
ber of debugging-related output lines whenever something re‐
lated to job signal handling occurs (start a process, handle
SIGCHLD, wait for a process, etc). Well, some of it.

I’m posting this here after a quick test in the hope that it
helps someone, especially in comparing output against a code
base that is known to work, ceteris paribus.

Index: jobs.c
===================================================================
RCS file: /cvs/src/bin/mksh/jobs.c,v
retrieving revision 1.120
diff -u -p -r1.120 jobs.c
--- jobs.c      4 Mar 2016 14:26:13 -0000       1.120
+++ jobs.c      26 Jun 2016 16:04:36 -0000
@@ -139,7 +139,9 @@ static int const    tt_sigs[] = { SIGTSTP, 
 static void            j_set_async(Job *);
 static void            j_startjob(Job *);
 static int             j_waitj(Job *, int, const char *);
-static void            j_sigchld(int);
+static void            j_sigchld_impl(int);
+static void            j_sigchld_manual(int);
+static void            j_sigchld_intr(int);
 static void            j_print(Job *, int, struct shf *);
 static Job             *j_lookup(const char *, int *);
 static Job             *new_job(void);
@@ -169,7 +171,7 @@ j_init(void)
        (void)sigemptyset(&sm_sigchld);
        (void)sigaddset(&sm_sigchld, SIGCHLD);
 
-       setsig(&sigtraps[SIGCHLD], j_sigchld,
+       setsig(&sigtraps[SIGCHLD], j_sigchld_intr,
            SS_RESTORE_ORIG|SS_FORCE|SS_SHTRAP);
 #else
        /* Make sure SIGCHLD isn't ignored - can do odd things under SYSV */
@@ -499,6 +501,23 @@ exchild(struct op *t, int flags,
 
        /* create child process */
        forksleep = 1;
+       shellf("{D: exchild (no-sigsuspend %s, unemployed %s, noprospectofwork 
%s) before fork<%s>}\n",
+#ifdef MKSH_NO_SIGSUSPEND
+           "on",
+#else
+           "off",
+#endif
+#ifdef MKSH_UNEMPLOYED
+           "on",
+#else
+           "off",
+#endif
+#ifdef MKSH_NOPROSPECTOFWORK
+           "on",
+#else
+           "off",
+#endif
+           p->command);
        while ((cldpid = fork()) < 0 && errno == EAGAIN && forksleep < 32) {
                if (intrsig)
                        /* allow user to ^C out... */
@@ -518,6 +537,8 @@ exchild(struct op *t, int flags,
                errorf("can't fork - try again");
        }
        p->pid = cldpid ? cldpid : (procpid = getpid());
+       shellf("{D: after fork, child %d, in %s}\n", (int)p->pid,
+           cldpid ? "parent" : "child");
 
 #ifndef MKSH_UNEMPLOYED
        /* job control set up */
@@ -595,6 +616,7 @@ exchild(struct op *t, int flags,
 #endif
                Flag(FTALKING) = 0;
                cleartraps();
+               shellf("{D:child %d, handing over to exec}\n", (int)p->pid);
                /* no return */
                execute(t, (flags & XERROK) | XEXEC, NULL);
 #ifndef MKSH_SMALL
@@ -621,6 +643,7 @@ exchild(struct op *t, int flags,
                        coproc.job = (void *)j;
                }
                if (flags & XBGND) {
+                       shellf("{D:parent, backgrounding child %d}\n", 
(int)p->pid);
                        j_set_async(j);
                        if (Flag(FTALKING)) {
                                shf_fprintf(shl_out, "[%d]", j->job);
@@ -630,8 +653,10 @@ exchild(struct op *t, int flags,
                                shf_putchar('\n', shl_out);
                                shf_flush(shl_out);
                        }
-               } else
+               } else {
+                       shellf("{D:parent, waiting for child %d}\n", 
(int)p->pid);
                        rv = j_waitj(j, jwflags, "jw:last proc");
+               }
        }
 
 #ifndef MKSH_NOPROSPECTOFWORK
@@ -1115,6 +1140,7 @@ j_waitj(Job *j,
 #ifdef MKSH_NO_SIGSUSPEND
        sigset_t omask;
 #endif
+       shellf("{D:j_waitj called}\n");
 
        /*
         * No auto-notify on the job we are waiting on.
@@ -1132,17 +1158,21 @@ j_waitj(Job *j,
            ((flags & JW_STOPPEDWAIT) && j->state == PSTOPPED)) {
 #ifndef MKSH_NOPROSPECTOFWORK
 #ifdef MKSH_NO_SIGSUSPEND
+               shellf("{D:j_waitj waiting for job: pause (no sigsuspend)}\n");
                sigprocmask(SIG_SETMASK, &sm_default, &omask);
                pause();
                /* note that handlers may run here so they need to know */
                sigprocmask(SIG_SETMASK, &omask, NULL);
 #else
+               shellf("{D:j_waitj waiting for job: default (sigsuspend)}\n");
                sigsuspend(&sm_default);
 #endif
 #else
-               j_sigchld(SIGCHLD);
+               shellf("{D:j_waitj waiting for job: manual (once)}\n");
+               j_sigchld_manual(SIGCHLD);
 #endif
                if (fatal_trap) {
+                       shellf("{D:j_waitj waiting for job resulted in 
fatal_trap}\n");
                        int oldf = j->flags & (JF_WAITING|JF_W_ASYNCNOTIFY);
                        j->flags &= ~(JF_WAITING|JF_W_ASYNCNOTIFY);
                        runtraps(TF_FATAL);
@@ -1150,9 +1180,11 @@ j_waitj(Job *j,
                        j->flags |= oldf;
                }
                if ((flags & JW_INTERRUPT) && (rv = trap_pending())) {
+                       shellf("{D:j_waitj waiting for job resulted in 
trap_pending}\n");
                        j->flags &= ~(JF_WAITING|JF_W_ASYNCNOTIFY);
                        return (-rv);
                }
+               shellf("{D:j_waitj waiting for job resulted ok}\n");
        }
        j->flags &= ~(JF_WAITING|JF_W_ASYNCNOTIFY);
 
@@ -1305,7 +1337,7 @@ j_waitj(Job *j,
  */
 /* ARGSUSED */
 static void
-j_sigchld(int sig MKSH_A_UNUSED)
+j_sigchld_impl(int sig MKSH_A_UNUSED)
 {
        int saved_errno = errno;
        Job *j;
@@ -1336,6 +1368,8 @@ j_sigchld(int sig MKSH_A_UNUSED)
 
        getrusage(RUSAGE_CHILDREN, &ru0);
        do {
+               char dbg[1000];
+
 #ifndef MKSH_NOPROSPECTOFWORK
                pid = waitpid(-1, &status, (WNOHANG |
 #if defined(WCONTINUED) && defined(WIFCONTINUED)
@@ -1345,6 +1379,8 @@ j_sigchld(int sig MKSH_A_UNUSED)
 #else
                pid = wait(&status);
 #endif
+               snprintf(dbg, sizeof(dbg), "{D:j_sigchld waited for job, got 
%d}\n", pid);
+               write(2, dbg, strlen(dbg));
 
                /*
                 * return if this would block (0) or no children
@@ -1362,6 +1398,7 @@ j_sigchld(int sig MKSH_A_UNUSED)
                                        goto found;
  found:
                if (j == NULL) {
+                       write(2, "{D:j_sigchld did not find job}\n", 31);
                        /* Can occur if process has kids, then execs shell
                        warningf(true, "bad process waited for (pid = %d)",
                                pid);
@@ -1369,6 +1406,7 @@ j_sigchld(int sig MKSH_A_UNUSED)
                        ru0 = ru1;
                        continue;
                }
+               write(2, "{D:j_sigchld found job}\n", 24);
 
                timeradd(&j->usrtime, &ru1.ru_utime, &j->usrtime);
                timersub(&j->usrtime, &ru0.ru_utime, &j->usrtime);
@@ -1398,16 +1436,33 @@ j_sigchld(int sig MKSH_A_UNUSED)
        }
 #ifndef MKSH_NOPROSPECTOFWORK
            while (/* CONSTCOND */ 1);
+       write(2, "{D:j_sigchld ended waiting continuously}\n", 41);
 #else
            while (/* CONSTCOND */ 0);
+       write(2, "{D:j_sigchld ended waiting once}\n", 33);
 #endif
+       goto j_sigchld_out2;
 
  j_sigchld_out:
+       write(2, "{D:j_sigchld ended waiting via goto}\n", 37);
+ j_sigchld_out2:
 #ifdef MKSH_NO_SIGSUSPEND
        sigprocmask(SIG_SETMASK, &omask, NULL);
 #endif
        errno = saved_errno;
 }
+static void
+j_sigchld_manual(int sig)
+{
+       write(2, "{D:j_sigchld called manually}\n", 30);
+       j_sigchld_impl(sig);
+}
+static void
+j_sigchld_intr(int sig)
+{
+       write(2, "{D:j_sigchld called from interrupt handler}\n", 44);
+       j_sigchld_impl(sig);
+}
 
 /*
  * Called only when a process in j has exited/stopped (ie, called only


Enjoy,
//mirabilos
-- 
Stéphane, I actually don’t block Googlemail, they’re just too utterly
stupid to successfully deliver to me (or anyone else using Greylisting
and not whitelisting their ranges). Same for a few other providers such
as Hotmail. Some spammers (Yahoo) I do block.

Reply via email to