jeff@fluke.UUCP (Jeff Stearns) (01/31/85)
e shell scripts to fail in mysterious and non-deterministic ways. Repeat-By: Arrange for awk to pipe some data to a slow-running process such as sort. When awk is finished, it will exit without waiting for its child: </etc/passwd awk '{ print $0 | "sort" }' >/tmp/awkout # Now note that the size changes as sort continues to run: wc /tmp/awkout wc /tmp/awkout wc /tmp/awkout wc /tmp/awkout Fix: My previous bug report included a bogus bug fix which would fail under some race conditions. Here is a proper bug fix which works. Two files are affected: main.c and run.c: *** main.c.old Wed Jan 30 14:47:01 1985 --- main.c Wed Jan 30 14:45:27 1985 *************** *** 89,94 exit(0); } run(); exit(errorflag); } --- 89,102 ----- exit(0); } run(); + /* + * Awk may have spawned some children (printf "....." | sort). + * The children may still be alive (sort can be quite slow). + * It is a bad idea to exit before our children have completed, + * as the next command to be executed may depend on ALL of our + * processing being complete. Thus we wait for our kids. + */ + WaitForChildren(); exit(errorflag); } *** run.c.old Wed Jan 30 14:47:21 1985 --- run.c Wed Jan 30 14:45:50 1985 *************** *** 13,18 { FILE *fp; char *fname; } files[FILENUM]; FILE *popen(); --- 13,19 ----- { FILE *fp; char *fname; + int CreatedByPopen; } files[FILENUM]; FILE *popen(); *************** *** 858,863 if (i >= FILENUM) error(FATAL, "too many output files %d", i); if (a == '|') /* a pipe! */ files[i].fp = popen(x.optr->sval, "w"); else if (a == APPEND) files[i].fp = fopen(x.optr->sval, "a"); --- 859,865 ----- if (i >= FILENUM) error(FATAL, "too many output files %d", i); if (a == '|') /* a pipe! */ + files[i].CreatedByPopen = 1, /* so we remember to pclose it */ files[i].fp = popen(x.optr->sval, "w"); else if (a == APPEND) files[i].fp = fopen(x.optr->sval, "a"); *************** *** 872,875 fflush(files[i].fp); /* in case someone is waiting for the output */ #endif tempfree(x); } --- 874,894 ----- fflush(files[i].fp); /* in case someone is waiting for the output */ #endif tempfree(x); + } + + /* + * Awk may have spawned some children (printf "....." | sort). + * The children may still be alive (sort can be quite slow). + * It is a bad idea to exit before our children have completed, + * as the next command to be executed may depend on ALL of our + * processing being complete. Thus we wait for our kids. + */ + WaitForChildren () { + int i; + for (i=0; i<FILENUM; i++) { + if (files[i].fp && files[i].CreatedByPopen) { + (void) pclose (files[i].fp); + files[i].fp = 0; + } + } } -- Jeff Stearns (206) 356-5064 John Fluke Mfg. Co. P.O. Box C9090 Everett WA 98043 {uw-beaver,decvax!microsof,ucbvax!lbl-csam,allegra,ssc-vax}!fluke!jeff