retitle 561203 FTBFS [hppa] - pthread_create() (or QThread) + fork() = crash reassign 561203 libc6 2.10.2-2 affects 561203 kde4libs tags 561203 help thanks Hello, when investigating this issue further, I determined that fork() following pthread_create() sometimes makes the application crash. In order to reproduce, build attached minifail.cpp with: $ g++ -I/usr/include/qt4 -lQtCore minifail.cpp -o minifail -O0 -g (pipe()/read()/write() are only used to sync parent with child after fork(), they are irrelevant for the problem). ------------------------------------ When repeatedly running it as `minifail` (pure_test() mode), I get: $ i=0; while true; do i=$(($i+1)); echo Run $i; ./minifail; done; Run 1 Child OK. Thread OK. Run 2 Thread OK. Child OK. Run 3 Thread OK. Segmentation fault Run 4 Thread OK. Segmentation fault Run 5 Thread OK. Segmentation fault Run 6 Child OK. Thread OK. Run 7 Child OK. Thread OK. Run 8 Child OK. Thread OK. Run 9 Child OK. Thread OK. Run 10 Child OK. Thread OK. Run 11 Child OK. Thread OK. Run 12 Thread OK. Child OK. Run 13 Child OK. Thread OK. Run 14 Thread OK. Child OK. Run 15 Thread OK. Child OK. Run 16 Child OK. Thread OK. Run 17 Child OK. Thread OK. Run 18 Thread OK. Child OK. Run 19 Thread OK. Child OK. Run 20 Segmentation fault Run 21 Segmentation fault Run 22 Child OK. Thread OK. Run 23 Thread OK. Segmentation fault Run 24 Thread OK. Child OK. Run 25 Thread OK. Child OK. Run 26 Thread OK. Segmentation fault Run 27 Child OK. Thread OK. Run 28 Child OK. Thread OK. Run 29 Child OK. Thread OK. Run 30 Child OK. Thread OK. Run 31 Child OK. Thread OK. The hang which is original problem of this FTBFS, can be reproduced with `./minifail qt` (qt_test() mode that uses QThread + fork()). QThread internally uses pthreads but unfortunately I was not able to reproduce the hang with pure pthread_* calls. $ i=0; while true; do i=$(($i+1)); echo Run $i; ./minifail qt; done; Run 1 Child OK. Thread OK. Run 2 Child OK. Thread OK. Run 3 Child OK. Thread OK. Run 4 Segmentation fault Run 5 Child OK. Thread OK. Run 6 Child OK. Thread OK. Run 7 Child OK. When attaching gdb to the hung minifail process, I get: 0x40f6db90 in __pthread_cond_wait_internal () from /lib/libpthread.so.0 (gdb) thread apply all bt Thread 2 (Thread 0x41b5c480 (LWP 28185)): #0 0x40838214 in clone () from /lib/libc.so.6 #1 0x00000000 in ?? () Thread 1 (Thread 0x400040c0 (LWP 28184)): #0 0x40f6db90 in __pthread_cond_wait_internal () from /lib/libpthread.so.0 #1 0x40f6e278 in pthread_cond_wait@@GLIBC_2.3.2 () from /lib/libpthread.so.0 #2 0x40847e88 in pthread_cond_wait () from /lib/libc.so.6 #3 0x404e5a68 in QWaitConditionPrivate::wait (this=0x27fd8, mutex=0x27fc4, time=4294967295) at thread/qwaitcondition_unix.cpp:87 #4 QWaitCondition::wait (this=0x27fd8, mutex=0x27fc4, time=4294967295) at thread/qwaitcondition_unix.cpp:159 #5 0x404e4128 in QThread::wait (this=<value optimized out>, time=4294967295) at thread/qthread_unix.cpp:484 #6 0x000110f0 in qt_test (argc=2, argv=0xfaf8e020) at minifail.cpp:39 #7 0x00011328 in main (argc=2, argv=0xfaf8e020) at minifail.cpp:77 (gdb) t 2 [Switching to thread 2 (Thread 0x41b5c480 (LWP 28185))]#0 0x40838214 in clone () from /lib/libc.so.6 (gdb) x/10i 0x40838214 0x40838214 <clone+24>: stw,ma r26,40(r25) 0x40838218 <clone+28>: stw r23,-3c(r25) 0x4083821c <clone+32>: stw r24,-38(r25) 0x40838220 <clone+36>: copy r24,r26 0x40838224 <clone+40>: ldw -74(sp),r24 0x40838228 <clone+44>: ldw -78(sp),r23 0x4083822c <clone+48>: ldw -7c(sp),r22 0x40838230 <clone+52>: copy r19,r4 0x40838234 <clone+56>: be,l 100(sr2,r0),sr0,r31 0x40838238 <clone+60>: ldi 78,r20 (gdb) x/20i clone 0x408381fc <clone>: stw rp,-14(sp) 0x40838200 <clone+4>: stw,ma r4,40(sp) 0x40838204 <clone+8>: stw sp,-4(sp) 0x40838208 <clone+12>: stw r19,-20(sp) 0x4083820c <clone+16>: cmpib,=,n 0,r26,0x40838270 <clone+116> 0x40838210 <clone+20>: cmpib,=,n 0,r25,0x40838270 <clone+116> 0x40838214 <clone+24>: stw,ma r26,40(r25) 0x40838218 <clone+28>: stw r23,-3c(r25) 0x4083821c <clone+32>: stw r24,-38(r25) 0x40838220 <clone+36>: copy r24,r26 0x40838224 <clone+40>: ldw -74(sp),r24 0x40838228 <clone+44>: ldw -78(sp),r23 0x4083822c <clone+48>: ldw -7c(sp),r22 0x40838230 <clone+52>: copy r19,r4 0x40838234 <clone+56>: be,l 100(sr2,r0),sr0,r31 0x40838238 <clone+60>: ldi 78,r20 0x4083823c <clone+64>: ldi -1000,r1 0x40838240 <clone+68>: cmpclr,>>= r1,ret0,r0 0x40838244 <clone+72>: b,l,n 0x4083825c <clone+96>,r0 0x40838248 <clone+76>: copy r4,r19 (gdb) This means that thread 2 was not started at all and hung at clone(). Relevant QThread code at http://qt.gitorious.org/qt/qt/blobs/4.5/src/corelib/thread/qthread_unix.cpp ------------------------------------ I strongly believe that if you fix the first problem, the 2nd one will disappear too as their origin is the same. Both tests work just fine on amd64. Contrary to what I said previously, the bug is reproducible under strace -f, but you have to wait much longer (up to 10000th run). ii libc6 2.10.2-2 GNU C Library: Shared libraries -- Modestas Vainius <modestas@vainius.eu>
#include <QtCore/QCoreApplication> #include <QtCore/QThread> #include <pthread.h> #include <stdio.h> #include <stdlib.h> class MyThread : public QThread { void run(); }; void MyThread::run() { printf("Thread OK.\n"); } int qt_test(int argc, char** argv) { QCoreApplication app(argc, argv); MyThread thread; thread.start(); int p[2]; char buf; pipe(p); switch (fork()) { case -1: perror("fork() failed"); case 0: printf("Child OK.\n"); write(p[1], "\0", 1); exit(0); default: break; } close(p[1]); read(p[0], &buf, 1); thread.wait(); return 0; } void* thread_run(void* arg) { printf("Thread OK.\n"); } int pure_test() { pthread_t thread; pthread_create(&thread, NULL, thread_run, NULL); int p[2]; char buf; pipe(p); switch (fork()) { case -1: perror("fork() failed"); case 0: close(p[0]); printf("Child OK.\n"); write(p[1], "\0", 1); exit(0); default: break; } close(p[1]); read(p[0], &buf, 1); pthread_join(thread, NULL); return 0; } int main(int argc, char** argv) { if (argc == 2) { if (!strcmp("qt", argv[1])) { return qt_test(argc, argv); } } return pure_test(); }
Attachment:
signature.asc
Description: This is a digitally signed message part.