Date: Wed, 11 Apr 2012 16:11:30 +0200 From: Mel Flynn <rflynn@acsalaska.net> To: FreeBSD Hackers <freebsd-hackers@FreeBSD.org> Subject: Debugging zombies: pthread_sigmask and sigwait Message-ID: <4F859112.5070005@acsalaska.net>
next in thread | raw e-mail | index | archive | help
This is a multi-part message in MIME format. --------------050201080106010708050901 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit Hi, I'm currently stuck on a bug in Zarafa-spooler that creates zombies. and working around it by claiming that our pthread library isn't "normal" which uses standard signals rather then a signal thread. My limited understanding of these facilities is however not enough to see the actual problem here and reading of related manpages did not lead me to a solution either. A test case reproducing the problem is attached. What happens is that SIGCHLD is never received by the signal thread and the child processes turn to zombies. Signal counters never go up, not even for SIGINFO, which I added specifically to see if anything gets through at all. The signal thread shows being stuck in sigwait. It's reproducible on 8.3-PRERELEASE of a few days ago (r233768). I'm not able to test it on anything newer unfortunately, but I suspect this is a bug/linuxism in the code not in FreeBSD. Thanks in advance for any insights. -- Mel --------------050201080106010708050901 Content-Type: text/plain; charset=windows-1252; name="BSDmakefile.txt" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="BSDmakefile.txt" PROG=spoolerbug NO_MAN=yes DEBUG_FLAGS=-g3 WARNS=6 WITH_DEBUG=yes LDFLAGS+=-pthread .include "../mk/core.mk" .include <bsd.prog.mk> --------------050201080106010708050901 Content-Type: text/plain; charset=windows-1252; name="spoolerbug.c" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="spoolerbug.c" /* * vim: ts=4 sw=4 tw=78 noet ai fdm=marker */ #include <sys/cdefs.h> __FBSDID("$FreeBSD$"); #include <sys/types.h> #include <sys/wait.h> #include <pthread.h> #include <signal.h> /* signal related */ #include <unistd.h> /* vfork */ #include <stdlib.h> /* arc4random() */ #include <stdbool.h> #include <getopt.h> #include <stdio.h> /* printing */ #include <err.h> #define SERVER_ITERATIONS 3 /* declarations */ void *signal_handler(void *); int running_server(void); void process_signal(int); /* globals */ pthread_t signal_thread; sigset_t signal_mask; bool bQuit = false; pid_t lastPid = 0; char *szCommand; size_t n_sigs_handled = 0; size_t n_sigs_child = 0; size_t n_sigs_info = 0; void * signal_handler(void *args __unused) { int sig; while( !bQuit && sigwait(&signal_mask, &sig) == 0 ) { n_sigs_handled++; process_signal(sig); } return NULL; } int running_server(void) { u_int32_t r, max = 10; pid_t pid, me; int i = 0; me = getpid(); warnx("[master]: Send SIGINFO to %u", (unsigned)me); do { warnx("[master]: lastPid = %u, n_sigs_handled=%zu, n_sigs_child=%zu" "n_sigs_info=%zu", (unsigned)lastPid, n_sigs_handled, n_sigs_child, n_sigs_info); pid = vfork(); if( pid < 0 ) break; if( pid == 0 ) { execl(szCommand, getprogname(), "-F", NULL); _exit(EXIT_FAILURE); } else { if( bQuit ) break; warnx("[master]: Child spawned with pid %u", (unsigned)pid); r = arc4random() % max; sleep((unsigned int)r); } } while( !bQuit && i++ < SERVER_ITERATIONS ); return (0); } void process_signal(int sig) { int stat; pid_t pid; switch(sig) { case SIGTERM: case SIGINT: bQuit = true; break; case SIGCHLD: n_sigs_child++; while( (pid = waitpid(-1, &stat, WNOHANG)) > 0) { lastPid = pid; } break; case SIGINFO: n_sigs_info++; break; default: signal(sig, SIG_IGN); break; } } int main(int argc, char *argv[]) { bool bForked = false; const char *opts = "F"; int ch, hr, rc; szCommand = argv[0]; while( (ch = getopt(argc, argv, opts)) != -1 ) { if( ch == 'F' ) bForked = true; } argc -= optind; argv += optind; if( !bForked ) { sigemptyset(&signal_mask); sigaddset(&signal_mask, SIGTERM); sigaddset(&signal_mask, SIGINT); sigaddset(&signal_mask, SIGCHLD); sigaddset(&signal_mask, SIGINFO); } daemon(1, 1); if( !bForked ) { rc = pthread_sigmask(SIG_BLOCK, &signal_mask, NULL); if( rc != 0 ) err(EXIT_FAILURE, "pthread_sigmask()"); pthread_create(&signal_thread, NULL, signal_handler, NULL); hr = running_server(); warnx("[master]: Joining signal thread"); pthread_join(signal_thread, NULL); } else { printf("Child says hello\n"); sleep(1); hr = 0; } return (hr); } --------------050201080106010708050901--
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?4F859112.5070005>