net@tub.UUCP (Oliver Laumann) (10/15/90)
I think I've found the bug that causes the NNTP 1.5.10 server to get into a mode where it prints "spawn: pipe: Too many open files" for every incoming article. The culprit is the call to vfork() followed by a call to closelog() in the child process in server/spawn.c. closelog() not only closes the file descriptor used by syslog(), but also sets (or clears; I don't have the sources) a variable shared between closelog and syslog to indicate that the socket must be re-opened in the next call to syslog(). Since spawn.c uses vfork() instead of fork(), this variable is also set or cleared in the parent process, so that the next call to syslog() re-opens the socket, although it has only been closed in the child process. This is repeated until all available file descriptors are in use. I don't know an easy fix for this other than replacing vfork by fork. Regards, -- Oliver Laumann net@TUB.BITNET net@tub.cs.tu-berlin.de net@tub.UUCP
leres@ace.ee.lbl.gov (Craig Leres) (10/16/90)
Oliver Laumann writes: > The culprit is the call to vfork() followed by a call to closelog() in > the child process in server/spawn.c. closelog() not only closes the > file descriptor used by syslog(), but also sets (or clears; I don't have > the sources) a variable shared between closelog and syslog to indicate > that the socket must be re-opened in the next call to syslog(). Too true. Personally, I dislike code that closes all fd's after forking. It tends to break things like syslog and yp and in fact the closelog() code is my fix. I didn't have any problems with it since we're a cnews site and enqueue() uses fork() instead of vfork(). Anyway, if we must keep the child close() loop, seems like the best solution is to move the closelog() to before the vfork(). This way both the parent and the child will know to reopen the fd. And since most openlog's()'s delay the syslog socket open until the first actual syslog(), this shouldn't be too expensive. Experimental context diff for the adventurous follows. Craig ------ RCS file: RCS/spawn.c,v retrieving revision 1.10 diff -c -r1.10 spawn.c *** /tmp/,RCSt1a14422 Mon Oct 15 21:25:25 1990 --- spawn.c Mon Oct 15 21:23:48 1990 *************** *** 164,169 **** --- 164,178 ---- * whatever), open "tempfile" for input, thus making * it stdin, and then execle the inews. We think. */ + #ifdef SYSLOG + /* + * Close in such a way that syslog() will know to reopen. + * We must do this before the vfork() otherwise the parent + * will think the syslog fd is closed and open a new one, + * eventually using up all the available file descriptors. + */ + closelog(); + #endif pid = vfork(); if (pid == 0) { /* We're in child */ *************** *** 183,192 **** } (void) dup2(1, 2); - #ifdef SYSLOG - /* Close in such a way that syslog() will know to reopen */ - closelog(); - #endif for (i = 3; i < 10; ++i) /* XXX but getdtablesize is too big */ (void) close(i); --- 192,197 ----