As I've mentioned before, I believe there are still problems with the multiuser handling in nntpcached. For instance, there are several places where lockex is called without the return status being checked. I added such a check, and found that it could indeed fail. From my log: Feb 13 23:26:53 newscache nntpcached[6389]: xover.c:646:Bad file descriptor: unable to lockex 'doffen.uninett.no/no/amiga/8192_xover' Feb 15 05:20:14 newscache nntpcached[8081]: xover.c:646:Bad file descriptor: unable to lockex 'doffen.uninett.no/comp/sys/hp/hpux/60928_xover' Feb 15 21:50:12 newscache nntpcached[9038]: xover.c:646:Bad file descriptor: unable to lockex 'doffen.uninett.no/comp/security/misc/37888_xover' Below is a patch which adds a check on the return status from lockex, and logs failures. Note that in the cases where the lock is not granted, it still sets xf->locked = TRUE which is obviously wrong. Just so you don't believe I have *solved* the problem yet :-) The patch also tries to make the error messages which log a file name a bit more uniform. Steinar Haug, Nethelp consulting, sthaug@nethelp.no ---------------------------------------------------------------------- *** xover.c.orig Tue Oct 15 10:43:06 1996 --- xover.c Sat Feb 15 22:30:05 1997 *************** *** 405,411 **** lseek (xf->fd, 0, SEEK_END) < 4 * MI || write (xf->fd, xf->outbuf, xf->outbuf_used) != xf->outbuf_used) { ! log (("unable to write/lseek '%s/%s' correctly (...unlinking)", CurrentDir, xf->dir, xf->name)); unlink (xf->name); } xf_release_writer (xf); --- 405,411 ---- lseek (xf->fd, 0, SEEK_END) < 4 * MI || write (xf->fd, xf->outbuf, xf->outbuf_used) != xf->outbuf_used) { ! loge (("unable to write/lseek '%s/%s' correctly (...unlinking)", xf->dir, xf->name)); unlink (xf->name); } xf_release_writer (xf); *************** *** 581,590 **** fd = open (fn, O_RDWR | O_CREAT, 0664); if (fd < 0 || fstat (fd, &st) < 0) { ! loge (("unable to open/create/fstat %s/%s", CurrentDir, fn)); goto auth_xover; } ! lockex (fd); xf = xf_add (t); xf->fd = fd; xf->name = Sstrdup (fn); --- 581,593 ---- fd = open (fn, O_RDWR | O_CREAT, 0664); if (fd < 0 || fstat (fd, &st) < 0) { ! loge (("unable to open/create/fstat '%s/%s'", CurrentDir, fn)); goto auth_xover; } ! if (lockex (fd) < 0) ! { ! loge (("unable to lockex '%s/%s'", CurrentDir, fn)); ! } xf = xf_add (t); xf->fd = fd; xf->name = Sstrdup (fn); *************** *** 638,644 **** { if (!xf->locked) /* size can't change if we have locked it */ { ! lockex (xf->fd); xf->locked = TRUE; if (fstat (xf->fd, &st) < 0) { --- 641,650 ---- { if (!xf->locked) /* size can't change if we have locked it */ { ! if (lockex (xf->fd) < 0) ! { ! loge (("unable to lockex '%s/%s'", xf->dir, xf->name)); ! } xf->locked = TRUE; if (fstat (xf->fd, &st) < 0) { *************** *** 768,781 **** xf_cached = TRUE; if (fstat (xf->fd, &st) < 0) { ! loge (("couldn't fstat(\"%s/%s\") (...unlinked)", xf->dir, xf->name)); goto bad; } if (st.st_size <= MI * 4) { if (!xf_cached) { ! loge (("short file, %d bytes %s/%s (...unlinked)", st.st_size, xf->dir, xf->name)); goto bad; } xf_release_reader (xf); --- 774,787 ---- xf_cached = TRUE; if (fstat (xf->fd, &st) < 0) { ! loge (("unable to fstat '%s/%s' (...unlinked)", xf->dir, xf->name)); goto bad; } if (st.st_size <= MI * 4) { if (!xf_cached) { ! loge (("short file, %d bytes '%s/%s' cwd %s (...unlinked)", st.st_size, xf->dir, xf->name, CurrentDir)); goto bad; } xf_release_reader (xf); *************** *** 799,805 **** xf->buf = Smalloc (MI * 4); if (read (xf->fd, xf->buf, MI * 4) != MI * 4) { ! loge (("couldn't read all %d bytes from %s/%s) (...unlinked)", MI * 4, xf->dir, xf->name)); goto bad; } } --- 805,811 ---- xf->buf = Smalloc (MI * 4); if (read (xf->fd, xf->buf, MI * 4) != MI * 4) { ! loge (("couldn't read all %d bytes from '%s/%s' (...unlinked)", MI * 4, xf->dir, xf->name)); goto bad; } } *************** *** 810,816 **** { if (lseek (xf->fd, 4 * MI, SEEK_SET) != 4 * MI) { ! loge (("couldn't lseek to %d in %s/%s (...unlinked)", MI * 4, xf->dir, xf->name)); goto bad; } xf->buf = Srealloc (xf->buf, xf->size); --- 816,822 ---- { if (lseek (xf->fd, 4 * MI, SEEK_SET) != 4 * MI) { ! loge (("couldn't lseek to %d in '%s/%s' (...unlinked)", MI * 4, xf->dir, xf->name)); goto bad; } xf->buf = Srealloc (xf->buf, xf->size); *************** *** 820,826 **** rb = xf_cached? xf->size - 4*MI: xf->size; if (read (xf->fd, xf_cached? xf->buf + 4*MI: xf->buf, rb) != rb) { ! loge (("couldn't read all of %d bytes from %s/%s (...unlinked)", rb, xf->dir, xf->name)); goto bad; } xover_buf = xf->buf + 4 * MI; --- 826,832 ---- rb = xf_cached? xf->size - 4*MI: xf->size; if (read (xf->fd, xf_cached? xf->buf + 4*MI: xf->buf, rb) != rb) { ! loge (("couldn't read all of %d bytes from '%s/%s' (...unlinked)", rb, xf->dir, xf->name)); goto bad; } xover_buf = xf->buf + 4 * MI; *************** *** 866,872 **** { if (offset >= xf->size) { ! loge (("bad xover offset in %s/%s (%d >= %d) (...unlinked)", xf->dir, xf->name, offset, xf->size)); goto bad; } xov = xover_buf + offset - 4 * MI; --- 872,878 ---- { if (offset >= xf->size) { ! loge (("bad xover offset in '%s/%s' (%d >= %d) (...unlinked)", xf->dir, xf->name, offset, xf->size)); goto bad; } xov = xover_buf + offset - 4 * MI; *************** *** 874,885 **** { if (lseek (xf->fd, offset, SEEK_SET) != offset) { ! loge (("lseek failed for %s/%s (...unlinked)", xf->dir, xf->name)); goto bad; } if (read (xf->fd, xover, len) != len) { ! loge (("only read part of %s/%s (...unlinked)", xf->dir, xf->name)); goto bad; } xov = xover; --- 880,891 ---- { if (lseek (xf->fd, offset, SEEK_SET) != offset) { ! loge (("lseek failed for '%s/%s' (...unlinked)", xf->dir, xf->name)); goto bad; } if (read (xf->fd, xover, len) != len) { ! loge (("only read part of '%s/%s' (...unlinked)", xf->dir, xf->name)); goto bad; } xov = xover; *************** *** 888,894 **** char *blocker; if (FILT && (blocker = xover_filter(xov, overviewFmt))) { ! logd (("content filter %s blocked xover of %s/%d", blocker, CurrentDir, xn)); } else { if (xhdr) --- 894,900 ---- char *blocker; if (FILT && (blocker = xover_filter(xov, overviewFmt))) { ! logd (("content filter %s blocked xover of '%s/%d'", blocker, CurrentDir, xn)); } else { if (xhdr) *************** *** 905,910 **** --- 911,917 ---- continue; bad: xf_close (xf); + logt (("unlinking %s dir %s cwd %s", xf->name, xf->dir, CurrentDir)); unlink (xf->name); continue; }