Messages in this thread | | | Date | Tue, 28 Oct 2008 23:29:45 -0500 | Subject | Strange stop-signal behavior in multithreaded program with defunct main | From | Michael Kerrisk <> |
| |
Bert Wesarg described a scenario that I quickly replicated on 2.6.28-rc2 (and 2.6.25 -- it's not a regression in 2.6.28-rc) using the program below: if we have a multithreaded process with a defunct main thread running on a tty, and that process is sent a stop signal (either ^Z (SIGTSTP) or a stop signal sent from another terminal using kill(1)), then:
a) the terminal is locked up; and
b) the program is unresponsive to any other signal, except SIGKILL or SIGCONT.
An example run: $ ./pthreads_zombie_main 1 # Creates one thread besides main 0: 0 0: 1 0: 2 ^Z
At this point, no shell prompt appears, and typing ^C (or ^\) has no effect. The process can be killed (and the terminal restored) by sending SIGKILL from another terminal. (If one instead types ^C at the terminal, and then sends SIGCONT from another terminal, then the terminal is restored and the program can be seen (via $?) to have terminated because of SIGINT.)
I'm (wildly) guessing that there is some problem in the terminal driver's understanding of the state and identify of the foreground job, but am not sure how to analyze this further. (I couldn't find a bug report or LKML thread that seemed to describe exactly this problem.) Ideas?
Cheers,
Michael
/* pthreads_zombie_main.c */
#include <pthread.h> #include <string.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <errno.h> #include <assert.h>
#define errExitEN(en, msg) { errno = en; perror(msg); \ exit(EXIT_FAILURE); }
static void * thread_start(void *arg) { int tnum = (int) arg; int j;
for (j = 0; ; j++) { sleep(3); printf("%d: %d\n", tnum, j); } }
int main(int argc, char *argv[]) { int s, tnum; pthread_t thr;
if (argc != 2) { fprintf(stderr, "Usage: %s <num-threads>\n", argv[0]); exit(EXIT_SUCCESS); }
for (tnum = 0; tnum < atoi(argv[1]); tnum++) { s = pthread_create(&thr, NULL, &thread_start, (void *) tnum); if (s != 0) errExitEN(s, "pthread_create"); }
pthread_exit(NULL); }
| |