Package: libc6-dev Version: 2.7-4 Severity: normal The following program exits with SEGV after sending a cancel signal to a single thread which is sitting in a nanosleep for 10s, with no mutexes held anywhere. The thread gets the segv, as far as I can tell in the handler, not the parent.
The program is compiled with -pthread. One can detatch the thread or not - it makes no difference. One can put the thread in deferred or asynchronous mode - it makes no difference. Typical output is ./testp2 (21019) created thread 21020 signal 11 received in pid 21020 after 1 cancel signals Segmentation fault The thread is just sitting in a nanosleep, as I said. It makes no difference if a handler for SEGV is set or not - it just prints the output message. CAVEAT: for all I know this is normal behaviour. Maybe one has to send a cancel message from a sibling thread, not a parent thread. Maybe "thread" has some special meaning in posix such as "whatever it is that may send a cancel message without causing a segv in the receiver", thus making the sender of a cancel message that does so inappropriate. Shrug. A strace -f shows that it is the child that gets the segv, while it's in the nanosleep. ... mprotect(0xb7f68000, 4096, PROT_READ) = 0 munmap(0xb7f86000, 102350) = 0 set_tid_address(0xb7e206f8) = 21058 sendto(-1209923840, umovestr: Input/output error 0xc, 3086491636, MSG_PROXY|MSG_EOR|MSG_TRUNC|MSG_FIN|MSG_SYN|0xb7e20000, NULL, 3215699728) = -1 ENOSYS (Function not implemented) futex(0xbfabaf00, 0x81 /* FUTEX_??? */, 1) = -1 ENOSYS (Function not implemented) rt_sigaction(SIGRTMIN, {0xb7f72260, [], SA_SIGINFO}, NULL, 8) = 0 rt_sigaction(SIGRT_1, {0xb7f722e0, [], SA_RESTART|SA_SIGINFO}, NULL, 8) = 0 rt_sigprocmask(SIG_UNBLOCK, [RTMIN RT_1], NULL, 8) = 0 getrlimit(RLIMIT_STACK, {rlim_cur=8192*1024, rlim_max=RLIM_INFINITY}) = 0 uname({sys="Linux", node="betty.it.uc3m.es", ...}) = 0 rt_sigaction(SIGSEGV, {0x8048720, [SEGV], SA_RESTART}, {SIG_DFL}, 8) = 0 gettid() = 21058 mmap2(NULL, 8388608, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7620000 brk(0) = 0x804a000 brk(0x806b000) = 0x806b000 mprotect(0xb7620000, 4096, PROT_NONE) = 0 clone(Process 21059 attached child_stack=0xb7e1f4c4, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID, parent_tidptr=0xb7e1fbd8, {entry_number:6, base_addr:0xb7e1fb90, limit:1048575, seg_32bit:1, contents:0, read_exec_only:0, limit_in_pages:1, seg_not_present:0, useable:1}, child_tidptr=0xb7e1fbd8) = 21059 [pid 21058] futex(0x8049d44, FUTEX_WAIT, 1, NULL <unfinished ...> [pid 21059] gettid() = 21059 [pid 21059] write(2, "(21058) created thread 21059\n", 29(21058) created thread 21059 ) = 29 [pid 21059] futex(0x8049d44, 0x5 /* FUTEX_??? */, 1 <unfinished ...> [pid 21058] <... futex resumed> ) = 0 [pid 21058] futex(0x8049cfc, FUTEX_WAIT, 2, NULL <unfinished ...> [pid 21059] <... futex resumed> ) = 1 [pid 21059] futex(0x8049cfc, FUTEX_WAKE, 1 <unfinished ...> [pid 21058] <... futex resumed> ) = 0 [pid 21058] futex(0x8049cfc, FUTEX_WAKE, 1) = 0 [pid 21058] nanosleep({0, 1000000}, <unfinished ...> [pid 21059] <... futex resumed> ) = 1 [pid 21059] nanosleep({10, 0}, <unfinished ...> [pid 21058] <... nanosleep resumed> {3215699704, 134514076}) = 0 [pid 21058] open("/etc/ld.so.cache", O_RDONLY) = 3 [pid 21058] fstat64(3, {st_mode=S_IFREG|0644, st_size=102350, ...}) = 0 [pid 21058] mmap2(NULL, 102350, PROT_READ, MAP_PRIVATE, 3, 0) = 0xb7f86000 [pid 21058] close(3) = 0 [pid 21058] access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory) [pid 21058] open("/lib/libgcc_s.so.1", O_RDONLY) = 3 [pid 21058] read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0p\31\0\000"..., 512) = 512 [pid 21058] fstat64(3, {st_mode=S_IFREG|0644, st_size=41876, ...}) = 0 [pid 21058] mmap2(NULL, 44964, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0xb7615000 [pid 21058] mmap2(0xb761f000, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x9) = 0xb761f000 [pid 21058] close(3) = 0 [pid 21058] munmap(0xb7f86000, 102350) = 0 [pid 21058] tgkill(21058, 21059, SIGRTMIN) = 0 [pid 21058] nanosleep({0, 1000000}, <unfinished ...> [pid 21059] <... nanosleep resumed> 0xb7e1f3c0) = ? ERESTART_RESTARTBLOCK (To be restarted) [pid 21059] --- SIGRTMIN (Unknown signal 32) @ 0 (0) --- [pid 21059] futex(0xb761fe84, FUTEX_WAKE, 2147483647) = 0 [pid 21059] --- SIGSEGV (Segmentation fault) @ 0 (0) --- [pid 21059] gettid() = 21059 [pid 21059] write(2, "signal 11 received in pid 21059 "..., 55signal 11 received in pid 21059 after 1 cancel signals ) = 55 [pid 21059] rt_sigaction(SIGSEGV, {SIG_IGN}, {0x8048720, [SEGV], SA_RESTART}, 8) = 0 [pid 21059] sigreturn() = ? (mask now [RTMIN]) [pid 21058] <... nanosleep resumed> {3215699704, 134514076}) = 0 [pid 21058] nanosleep({0, 1000000}, <unfinished ...> [pid 21059] --- SIGSEGV (Segmentation fault) @ 0 (0) --- Process 21059 detached <... nanosleep resumed> 0xbfabaee8) = ? ERESTART_RESTARTBLOCK (To be restarted) +++ killed by SIGSEGV +++ Process 21058 detached betty:/home/oboe/ptb% Here's the program. // compile line: gcc -O2 -pthread -g -o testp2 testp2.c #include <string.h> #include <stdio.h> #include <stdlib.h> #include <error.h> #include <errno.h> #include <time.h> #include <signal.h> #include <sys/types.h> #define _GNU_SOURCE /* or _BSD_SOURCE or _SVID_SOURCE */ #include <unistd.h> #include <sys/syscall.h> #define __USE_GNU 1 #include <pthread.h> static pthread_mutex_t mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP; static pthread_cond_t cond = PTHREAD_COND_INITIALIZER; static int kcount; static int debug; static t; // set when thread is ready to play static void print_error (int err, char *fnname, int line) { char buf[128]; fprintf (stderr, "error '%s' (%d) from %s line %d\n", strerror_r (err, buf, sizeof (buf)), err, fnname, line); } static void sighandler (int k) { fprintf (stderr, "signal %d received in pid %d after %d cancel signals\n", k, syscall (SYS_gettid), kcount); debug++; signal (k, SIG_IGN); } #define DEBUG(s ...) if (debug) { \ fprintf(stderr, "(%d) ", syscall(SYS_gettid)); \ fprintf(stderr, s); \ } static void do_thread_stuff (void) { // just wait for 10s in nanosleep struct timespec req = { 10, 0, }, rem; int err; complete_nanosleep: err = nanosleep (&req, &rem); if (err) { switch (errno) { case EFAULT: print_error (errno, "nanosleep", __LINE__); break; case EINTR: req = rem; goto complete_nanosleep; break; case EINVAL: print_error (errno, "nanosleep", __LINE__); break; } } } static void * tfn (void *tdata) { int err; // can try ASYNC mode here - no difference //err = pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); //if (err) { // print_error(err, "pthread_setcanceltype", __LINE__); // return NULL; //} /* * - tell the parent waiter that we are ready to play */ pthread_mutex_lock (&mutex); fprintf (stderr, "(%d) created thread %d\n", (pthread_t)tdata, syscall (SYS_gettid)); t++; // signal parent that thread is up and working pthread_cond_signal (&cond); pthread_mutex_unlock (&mutex); do_thread_stuff (); // just wait in nanosleep } int main () { pthread_t tid; int err; signal (SIGSEGV, sighandler); pthread_mutex_lock (&mutex); err = pthread_create (&tid, NULL, tfn, (void *)(long)(syscall(SYS_gettid))); if (err) { print_error (err, "pthread_create", __LINE__); return -err; } while (t <= 0) { pthread_cond_wait (&cond, &mutex); } // detach or not makes no difference //err = pthread_detach (tid); //if (err) { // print_error (err, "pthread_detach", __LINE__); // return -err; //} /* the thread is now ready and we have the lock on the * mutex. No other lock is held or will ever be held. * Release the lock and go play with cancel messages. */ pthread_mutex_unlock (&mutex); while (1) { // cancel the thread every millisecond struct timespec req = { 0, 1000000, }, rem; complete_nanosleep: err = nanosleep (&req, &rem); if (err) { switch (errno) { case EFAULT: print_error (errno, "nanosleep", __LINE__); break; case EINTR: req = rem; goto complete_nanosleep; break; case EINVAL: print_error (errno, "nanosleep", __LINE__); break; } } err = pthread_cancel (tid); if (err) { print_error (err, "pthread_cancel", __LINE__); } kcount++; } // never reached } -- System Information: Debian Release: lenny/sid APT prefers testing APT policy: (500, 'testing') Architecture: i386 (i686) Kernel: Linux 2.6.15.3 (PREEMPT) Locale: LANG=C, LC_CTYPE=C (charmap=ANSI_X3.4-1968) (ignored: LC_ALL set to C) Shell: /bin/sh linked to /bin/bash Versions of packages libc6-dev depends on: ii libc6 2.7-4 GNU C Library: Shared libraries ii linux-libc-dev 2.6.22-6 Linux Kernel Headers for developme Versions of packages libc6-dev recommends: ii gcc [c-compiler] 4:4.2.1-6 The GNU C compiler ii gcc-2.95 [c-compile 1:2.95.4-27 The GNU C compiler ii gcc-3.4 [c-compiler 3.4.6-6 The GNU C compiler ii gcc-4.1 [c-compiler 4.1.2-18 The GNU C compiler ii gcc-4.2 [c-compiler 4.2.2-4 The GNU C compiler ii tcc [c-compiler] 0.9.24~cvs20070502-2 the smallest ANSI C compiler -- no debconf information -- To UNSUBSCRIBE, email to [EMAIL PROTECTED] with a subject of "unsubscribe". Trouble? Contact [EMAIL PROTECTED]