upas/runq: wait for the child process to send back the message if it was rejected When a message cannot be delivered (eg. when the remote server reply with a permanent error), the message is sent back to the sender by spawning a child process (marshal). But runq doesn't wait for this process (returnmail()) and removes the message from disk (see remmatch()). The original code[1] used wait(), which has been removed from 9front with the commit ('runq: clean up code, fix error handling.')[2] which was a fix to the commit ('upas/runq: support parallel queue processing, drop -a')[3]. This commit will change back to wait for marshal if runq runs with one job (-n 1, which is the default setting) in order to avoid interfering with jobs created from rundir()[4], even if I don't understand how. [1]: http://9p.io/sources/plan9/sys/src/cmd/upas/q/runq.c [2]: http://git.9front.org/plan9front/plan9front/49d7ca8d92e5667f3e5ece4c6acbc1064701e2f8/commit.html [3]: http://git.9front.org/plan9front/plan9front/f321298c551e4333fcf2819eabf7ce67ea443e20/commit.html [4]: https://inbox.vuxu.org/9front/ZB+YbtCfhrrn6WyW@alice/ --- diff 437db15d657ab83cad4fbbe1f146331b0b1b894c 3a1cfac4391588869011879eaca26f0deccbbe04 --- a/sys/src/cmd/upas/q/runq.c +++ b/sys/src/cmd/upas/q/runq.c @@ -575,7 +575,8 @@ returnmail(char **av, Wdir *w, char *name, char *msg) { char buf[256], attachment[Pathlen], *sender; - int fd, pfd[2]; + int fd, pfd[2], rc; + Waitmsg *wm; long n; String *s; @@ -597,7 +598,7 @@ return -1; } - switch(rfork(RFFDG|RFPROC|RFENVG|RFNOWAIT)){ + switch(rfork(RFFDG|RFPROC|RFENVG|(njob != 1 ? RFNOWAIT : 0))){ case -1: logit("runq - fork failed", w, name, av); return -1; @@ -625,6 +626,7 @@ fprint(pfd[1], "%s ", av[n]); } fprint(pfd[1], "'' failed (code %s).\nThe symptom was:\n\n", msg); + rc = 0; fd = open(file(name, 'E'), OREAD); if(fd >= 0){ for(;;){ @@ -633,13 +635,28 @@ break; if(write(pfd[1], buf, n) != n){ close(fd); - return -1; + rc = -1; + goto out; } } close(fd); } close(pfd[1]); - return 0; +out: + if(njob == 1){ + rc = -1; + wm = wait(); + if(wm == nil) + syslog(0, runqlog, "wait failed: %r"); + else{ + if(wm->msg[0]) + syslog(0, runqlog, "returnmail child: %s", wm->msg); + else + rc = 0; + free(wm); + } + } + return rc; } /*