snoopy@sopwith.UUCP (Snoopy T. Beagle) (11/02/88)
If you are not running a Tektronix machine, and your news neighbors are not, it is probably safe for you to skip this article. There is a bug in the Tektronix implementation of the shared memory features (mmap(2) and friends) which were documented in the 4.[23] BSD manuals. It causes corruption of data sent from a parent to a child through a pipe. The stock rnews program corrupts news articles when run under a tekvm kernel. I have included a context diff for a kludge workaround for rnews below. This kludge fixes news unbatching, but there may be other programs which use pipes in this manner, so beware. Typical pipes between siblings as setup by normal shell command pipelines seem to work fine. The problem *may* be unique to parent->child pipes. All tekvm kernels tested have had the bug. No kernels tested using the stock BSD memory system have displayed the bug. If you are running the default kernel that came with release 2.2 or newer you are probably running a tekvm kernel. If you are running 2.1.1 or older software, if your machine is a 6200 series, or if your kernel claims to be "bsdvm" or "oldvm", you are probably safe. If you have been running news for awhile and are receiving your news in compressed batches and have not noticed any corruption of articles, you are probably safe. If you have questions about this, you may send me mail at the addresses below. Here is a context diff to ifuncs.c for rnews: ====================== cut here ================================= --- ifuncs.c *************** *** 1249,1254 int c; char *cp; setbuf(infp, (char *)NULL); while ((c = getc(infp)) == '#') { /* some kind of batch, investigate further */ --- 1249,1264 ----- int c; char *cp; + int avoid_pipe = 1; /* Kludge for tekvm: avoid using a pipe, + * since tekvm corrupts the data if a + * pipe is used. This forces rnews to + * always use a tmp file; less efficient, + * but the articles don't get corrupted. + * Kludge may be turned off when using + * bsdvm kernels by setting avoid_pipe + * to 0. + */ + setbuf(infp, (char *)NULL); while ((c = getc(infp)) == '#') { /* some kind of batch, investigate further */ *************** *** 1302,1308 if (rc <= 0) break; if (fd < 0) { ! if (rc == asize) break; /* fits in buffer */ if (!tfilename) { tfilename = "/tmp/unbnewsXXXXXX"; --- 1312,1318 ----- if (rc <= 0) break; if (fd < 0) { ! /* kludge for tekvm */ if ((!avoid_pipe) && (rc == asize)) break; /* fits in buffer */ if (!tfilename) { tfilename = "/tmp/unbnewsXXXXXX"; *************** *** 1342,1348 * of ourselves for each article and allow it * to process. */ ! if (rc == asize) { /* * article fits in buffer, use a pipe * instead of a temporary file. --- 1352,1358 ----- * of ourselves for each article and allow it * to process. */ ! /* tekvm kludge */ if ((!avoid_pipe) && (rc == asize)) { /* * article fits in buffer, use a pipe * instead of a temporary file. *************** *** 1355,1361 sleep(60); } if (pid == 0) { ! if (rc == asize) { /* article fits in buffer * make the output of the * pipe for STDIN --- 1365,1371 ----- sleep(60); } if (pid == 0) { ! /* tekvm kludge */ if ((!avoid_pipe) && (rc == asize)) { /* article fits in buffer * make the output of the * pipe for STDIN *************** *** 1375,1381 * normal article */ } /* parent of fork */ ! if (rc == asize) { /* article fits in buffer */ wc = write(piped[1], buf, rc); if (wc != rc) { --- 1385,1391 ----- * normal article */ } /* parent of fork */ ! /* tekvm kludge */ if ((!avoid_pipe) && (rc == asize)) { /* article fits in buffer */ wc = write(piped[1], buf, rc); if (wc != rc) { ====================== cut here ================================= _____ /_____\ Snoopy /_______\ |___| tektronix!tekecs!sopwith!snoopy |___| sun!nosun!illian!sopwith!snoopy