toddb@tekcrl.UUCP (Todd Brunhoff) (08/22/86)
Bill Sommerfeld <wesommer@athena.mit.edu> has done another marvelous job of finding another crash condition and providing the fix. These are his paraphrased comments followed by the diffs. When sleeping in rmt_getmsg, waiting to grab the connection, you didn't check to see if rp->close is true every time you wake up.. Imagine the following scenario: (watching this with debug set to 0xc00 helps) A: goes into the sleep waiting for the connection (on &rp->r_recver) B: does random remote i/o and sees the connection break in getmsg B: calls rmt_shutdown, sets rp->r_close to true, wakes up &rp->r_recver, B: returns error code from remoteio A: wakes up, grabs the connection A: drops right into rmt_uio where it attempts to access the socket A: falls down dead in sorecieve with a protection fault (scribbled socket). This fix also means that when there are multiple processes using a connection, and the connection dies, *ALL* of them wake up with error messages (not just the one which happened to be active at the time). This is a feature! RCS file: RCS/rmt_io.c,v retrieving revision 2.6 diff -c -r2.6 rmt_io.c *** /tmp/,RCSt1014402 Fri Aug 22 10:49:55 1986 --- rmt_io.c Fri Aug 22 10:41:54 1986 *************** *** 11,17 * may be copied, modified or used in any way, without fee, provided this * notice remains an unaltered part of the software. * ! * $Header: rmt_io.c,v 2.6 86/08/08 14:39:13 toddb Exp $ * * $Log: rmt_io.c,v $ * Revision 2.6 86/08/08 14:39:13 toddb --- 11,17 ----- * may be copied, modified or used in any way, without fee, provided this * notice remains an unaltered part of the software. * ! * $Header: rmt_io.c,v 2.7 86/08/22 10:37:11 toddb Exp $ * * $Log: rmt_io.c,v $ * Revision 2.7 86/08/22 10:37:11 toddb *************** *** 14,19 * $Header: rmt_io.c,v 2.6 86/08/08 14:39:13 toddb Exp $ * * $Log: rmt_io.c,v $ * Revision 2.6 86/08/08 14:39:13 toddb * Removed unnecessary printf from rmt_closehost(). * --- 14,26 ----- * $Header: rmt_io.c,v 2.7 86/08/22 10:37:11 toddb Exp $ * * $Log: rmt_io.c,v $ + * Revision 2.7 86/08/22 10:37:11 toddb + * While waiting for the use of the socket, the code in rmt_getmsg() + * neglected to check whether the connection was closed or closing. + * This meant that if it did close while a process was waiting, the + * process would begin to use an invalid socket. Fix by + * wesommer@athena.mit.edu. + * * Revision 2.6 86/08/08 14:39:13 toddb * Removed unnecessary printf from rmt_closehost(). * *************** *** 435,441 * that we are the recipient of this message. In fact, * the message may have already arrived. */ ! while (rp->r_recver != u.u_procp->p_pid && rp->r_recver != -1) sleep((caddr_t)&rp->r_recver, PZERO+1); if (rp->r_recver == u.u_procp->p_pid && rp->r_received) { auio.uio_resid = 0; --- 442,450 ----- * that we are the recipient of this message. In fact, * the message may have already arrived. */ ! while (rp->r_recver != u.u_procp->p_pid ! && rp->r_recver != -1 ! && ! rp->r_close) sleep((caddr_t)&rp->r_recver, PZERO+1); if (rp->r_close) break; *************** *** 437,442 */ while (rp->r_recver != u.u_procp->p_pid && rp->r_recver != -1) sleep((caddr_t)&rp->r_recver, PZERO+1); if (rp->r_recver == u.u_procp->p_pid && rp->r_received) { auio.uio_resid = 0; break; --- 446,453 ----- && rp->r_recver != -1 && ! rp->r_close) sleep((caddr_t)&rp->r_recver, PZERO+1); + if (rp->r_close) + break; if (rp->r_recver == u.u_procp->p_pid && rp->r_received) { auio.uio_resid = 0; break;