First, a hello to the other 3 people actually on this list, thanks for writing! Further thoughts on getpeername and select in sockets.c. Do both! Best of both worlds! if ((select (scfg->fd + 1, &rdfs, NULL, NULL, &tv) == 0) && (getpeername (scfg->fd, (struct sockaddr *) &sa, &sa_len) == 0)) And now onto the bug-du-jour... I was getting dead nntpcached's piling up on our system, probably from when dialup users disconnected (as in hung up). They were all getting stuck doing the final flush of their stdout. Here is a patch that fixes it. Two caveats. I wrote it at 2am, so I was more interested in "correct" than "fancy". I was almost going to add some state to the local alarm handling code, so that it could call itself it it bombed out in itself, and log an error and then _exit. Well, I didn't, it was 2AM. Also added a little protection for an alarm getting raised in a term and vice versa. The second caveat is that I only fixed the hang in the part of Exit that actually was hanging. Although it's been running for awhile with no new dead processes, it's possible that it'll find some new place to hang further up in Exit and I'll have to protect that too. So far, there hasn't been, this code works great! Oops, third caveat. On my system, the behavior of signal depend on which libraires you link in. If it seems like I'm being pedantic and setting things that would normaly default that way, that's why. That's also why I'm using sigaction instead of signal. Ok, here it is! *** nntpcache-1.0.7.1-stat2-REF/nntpcache.c Fri Aug 29 03:15:16 1997 --- nntpcache-1.0.7.1-stat2/nntpcache.c Mon Sep 01 09:08:52 1997 *************** *** 185,191 **** --- 188,204 ---- X (void Exit (int code)) { + #ifdef ORIG flush (); + #else + sigset_t set; + struct sigaction action; + /* don't let anyone interrupt us */ + sigemptyset(&set); + sigaddset(&set, SIGALRM); + sigaddset(&set, SIGTERM); + sigprocmask (SIG_BLOCK, &set, NULL); + #endif if (!Daemon || InDaemon) { dbzsync (); *************** *** 231,236 **** --- 244,267 ---- mmalloc_detach (Mbase); #endif closelog (); + + #ifndef ORIG + /* restore default SIGALRM behavior (ie, crash us out) */ + sigemptyset(&action.sa_mask); + sigaddset(&action.sa_mask, SIGALRM); + action.sa_flags = 0; + action.sa_handler = SIG_DFL; + sigaction(SIGALRM, &action, NULL); + + /* unblock, since we might be in a SIGALRM handler right now! */ + sigemptyset(&set); + sigaddset(&set, SIGALRM); + sigprocmask (SIG_UNBLOCK, &set, NULL); + + alarm(60); + flush (); /* better finish this in 60 seconds, toots. */ + logd (("clean shutdown.")); + #endif exit (code); } *************** *** 680,685 **** --- 711,720 ---- /* init_mmalloc(NULL); */ #endif + #ifndef ORIG + struct sigaction myaction; + #endif + if (strstr (VERSION, "UL")) fprintf (stderr, "\ NOTE: This version of NNTPCACHE is unlicensed. Government and\n\ *************** *** 842,848 **** --- 877,892 ---- Exit (1); } logd(("cwd now %s", con.cacheDir)); + #ifdef ORIG signal (SIGTERM, sigterm); + #else + sigemptyset(&myaction.sa_mask); + sigaddset(&myaction.sa_mask, SIGTERM); + sigaddset(&myaction.sa_mask, SIGALRM); + myaction.sa_flags = 0; + myaction.sa_handler = sigterm; + sigaction(SIGTERM, &myaction, NULL); + #endif signal (SIGINT, sigint); signal (SIGSEGV, sigsegv); signal (SIGFPE, SIG_IGN); *************** *** 1096,1106 **** --- 1144,1176 ---- #endif #endif } + #ifdef ORIG signal(SIGALRM, sigalrm); + #else + sigemptyset(&myaction.sa_mask); + sigaddset(&myaction.sa_mask, SIGALRM); + sigaddset(&myaction.sa_mask, SIGTERM); + myaction.sa_flags = 0; + myaction.sa_handler = sigalrm; + sigaction(SIGALRM, &myaction, NULL); + #endif alarm(con.idleTimeout);