X-Recipient: archive-cygwin AT delorie DOT com X-SWARE-Spam-Status: No, hits=1.4 required=5.0 tests=BAYES_50,SARE_BAYES_5x7,T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org X-cybertrench.com-virus-scan: clean Date: Mon, 12 Jul 2010 23:05:19 +0200 From: Corvus Corax To: cygwin AT cygwin DOT com Subject: Re: Sending SIGUSR1 to thread in nanosleep causes segfault Message-ID: <20100712230519.4e871a91@CorvusMC.home> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="MP_//2QRbacSOBFpiqJpH/m8fPe" Mailing-List: contact cygwin-help AT cygwin DOT com; run by ezmlm List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: cygwin-owner AT cygwin DOT com Mail-Followup-To: cygwin AT cygwin DOT com Delivered-To: mailing list cygwin AT cygwin DOT com --MP_//2QRbacSOBFpiqJpH/m8fPe Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 7bit Content-Disposition: inline FYI Just to update some details. I am working with James Cotton on the OpenPilot project. We are trying to port the POSIX simulation port of FreeRTOS to cygwin. We run into issues with signal handling in cygwin 1.7.5 that are currently blocking our development, since every method to suspend a running thread via signals either causes: - random segfaults within Cygwin DLL. or - failure to execute the signal handler. For the sake of narrowing down the source of our problems, we created 8 demo test cases. Each of them works the same way: 1. A thread is spawned via pthread_create(), which then executes some code that is supposed to "sleep the thread" in background. 2. Signals are repeatedly sent to that thread using pthread_kill() which are supposed to be handled by a signal handler. 3. Each succesful call to the signal handler writes a dot (.) to stderr (using the write() system call to be thread safe) Obviously what this is supposed to create is a neverending line of dots. (Tested and working on Linux and Mac OS X on several architectures) We believe this is a sign of a major flaw in cygwin signal handling and may possibly affect many applications. (Any application that uses signal handlers is potentially affected!) SEGFAULTS usually occur only once in several thousand signals, so it is a problem that won't appear on normal applications in a very frequent way. However it is definitely reproducable! All 8 test cases usually reach a stable state (segfault or freeze of output) within less than 10 seconds (usually less than 1s) of run time. The 8 test cases are as follows: ---- test_case_1_sleep.c - The thread sleeps (literally) calling sleep() from Bug: - After a couple thousand dots, the program ends with SIGSEGV in cygwin1.dll. The backtrace leads to garbage due to stack corruption! ---- test_case_2_nanosleep.c - The thread sleeps calling nanosleep() from Bug: - After a couple thousand dots, the program ends with SIGSEGV in cygwin1.dll. The backtrace leads to garbage due to stack corruption! ---- test_case_3_select.c - The thread sleeps calling select() from Bug: - Once select() is executed, cygwin blocks signals, failing to execute the signal handler. No dots are printed (There is a violation to POSIX specification. select() is supposed to return prematurely on receiving any signal, whether handled or not. This does not happen.) ---- test_case_4_mutex_lock.c - The thread sleeps calling pthread_mutex_lock() from Bug: - Once mutex_lock() is executed, cygwin blocks signals, failing to execute the signal handler. No dots are printed. This is a major issue for the porting of FreeRTOS, because it causes deadlocks we cannot resolve. ---- test_case_5_pselect.c - The thread sleeps calling pselect() from . Pselect allows to specify a signal mask of signals to be (or not to be) blocked during the pselect() call. The mask is deliberate set EMPTY to make pselect() interrupt on ALL signals. Bug: - Once pselect() is executed, cygwin blocks signals, failing to execute the signal handler. No dots are printed (pselect() completely ignores its signal mask argument !!!!! ) ---- test_case_6_sched_yield.c - The thread "sleeps" repeatedly calling sched_yield() from Bug: - The signal handler is not executed in a reliable fashion. ---- test_case_7_busy_waiting.c - The thread runs like crazy in a busy loop. Bug: - The signal handler is not executed in a reliable fashion. ---- test_case_8_io.c - The thread "sleeps" by executing a blocking "read()" call from stdin Bug: - The signal handler is not executed in a reliable fashion. - Occasional segfaults in cygwin dll. --MP_//2QRbacSOBFpiqJpH/m8fPe Content-Type: text/x-c++src Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename=test_case_1_sleep.c /** * small test program whether signals between threads work as they should */ #include #include #include void sighandler(int sig) { write(2,".",1); return; } void* threadstart(void* arg) { while (1) { sleep(1); } } int main(char** argc, int argv) { pthread_t testthread1; struct sigaction action; action.sa_handler=sighandler; action.sa_flags=0; sigfillset( &action.sa_mask ); sigaction(SIGUSR1,&action,NULL); pthread_create(&testthread1,NULL,threadstart,NULL); while (1) { pthread_kill(testthread1,SIGUSR1); } } --MP_//2QRbacSOBFpiqJpH/m8fPe Content-Type: text/x-c++src Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename=test_case_2_nanosleep.c /** * small test program whether signals between threads work as they should */ #include #include #include void sighandler(int sig) { write(2,".",1); return; } void* threadstart(void* arg) { struct timespec sleeptime; while (1) { sleeptime.tv_sec=1; sleeptime.tv_nsec=0; nanosleep(&sleeptime,NULL); } } int main(char** argc, int argv) { pthread_t testthread1; struct sigaction action; action.sa_handler=sighandler; action.sa_flags=0; sigfillset( &action.sa_mask ); sigaction(SIGUSR1,&action,NULL); pthread_create(&testthread1,NULL,threadstart,NULL); while (1) { pthread_kill(testthread1,SIGUSR1); } } --MP_//2QRbacSOBFpiqJpH/m8fPe Content-Type: text/x-c++src Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename=test_case_3_select.c /** * small test program whether signals between threads work as they should */ #include #include #include #include #include void sighandler(int sig) { write(2,".",1); return; } void* threadstart(void* arg) { struct timeval sleeptime; while (1) { sleeptime.tv_sec=1; sleeptime.tv_usec=0; select(0,NULL,NULL,NULL,&sleeptime); } } int main(char** argc, int argv) { pthread_t testthread1; struct sigaction action; action.sa_handler=sighandler; action.sa_flags=0; sigfillset( &action.sa_mask ); sigaction(SIGUSR1,&action,NULL); pthread_create(&testthread1,NULL,threadstart,NULL); while (1) { pthread_kill(testthread1,SIGUSR1); } } --MP_//2QRbacSOBFpiqJpH/m8fPe Content-Type: text/x-c++src Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename=test_case_4_mutex_lock.c /** * small etst program whether signals between threads work as they should */ #include #include static pthread_mutex_t Mutex = PTHREAD_MUTEX_INITIALIZER; /** * actual test program */ void sighandler(int sig) { write(2,".",1); return; } void* threadstart(void* arg) { while (1) { pthread_mutex_lock(&Mutex); } } int main(char** argc, int argv) { pthread_t testthread1; struct sigaction action; action.sa_handler=sighandler; action.sa_flags=0; sigfillset( &action.sa_mask ); sigaction(SIGUSR1,&action,NULL); pthread_mutex_lock(&Mutex); pthread_create(&testthread1,NULL,threadstart,NULL); while (1) { pthread_kill(testthread1,SIGUSR1); } } --MP_//2QRbacSOBFpiqJpH/m8fPe Content-Type: text/x-c++src Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename=test_case_5_pselect.c /** * small test program whether signals between threads work as they should */ #include #include #include #include #include void sighandler(int sig) { write(2,".",1); return; } void* threadstart(void* arg) { sigset_t sigset; struct timespec sleeptime; while (1) { sleeptime.tv_sec=1; sleeptime.tv_nsec=0; sigemptyset(&sigset); pselect(0,NULL,NULL,NULL,&sleeptime,&sigset); } } int main(char** argc, int argv) { pthread_t testthread1; struct sigaction action; action.sa_handler=sighandler; action.sa_flags=0; sigfillset( &action.sa_mask ); sigaction(SIGUSR1,&action,NULL); pthread_create(&testthread1,NULL,threadstart,NULL); while (1) { pthread_kill(testthread1,SIGUSR1); } } --MP_//2QRbacSOBFpiqJpH/m8fPe Content-Type: text/x-c++src Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename=test_case_6_sched_yield.c /** * small test program whether signals between threads work as they should */ #include #include #include void sighandler(int sig) { write(2,".",1); return; } void* threadstart(void* arg) { while (1) { sched_yield(); } } int main(char** argc, int argv) { pthread_t testthread1; struct sigaction action; action.sa_handler=sighandler; action.sa_flags=0; sigfillset( &action.sa_mask ); sigaction(SIGUSR1,&action,NULL); pthread_create(&testthread1,NULL,threadstart,NULL); while (1) { pthread_kill(testthread1,SIGUSR1); } } --MP_//2QRbacSOBFpiqJpH/m8fPe Content-Type: text/x-c++src Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename=test_case_7_busy_waiting.c /** * small test program whether signals between threads work as they should */ #include #include #include void sighandler(int sig) { write(2,".",1); return; } void* threadstart(void* arg) { while (1) { } } int main(char** argc, int argv) { pthread_t testthread1; struct sigaction action; action.sa_handler=sighandler; action.sa_flags=0; sigfillset( &action.sa_mask ); sigaction(SIGUSR1,&action,NULL); pthread_create(&testthread1,NULL,threadstart,NULL); while (1) { pthread_kill(testthread1,SIGUSR1); } } --MP_//2QRbacSOBFpiqJpH/m8fPe Content-Type: text/x-c++src Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename=test_case_8_io.c /** * small test program whether signals between threads work as they should */ #include #include #include void sighandler(int sig) { write(2,".",1); return; } void* threadstart(void* arg) { char buf[1024]; while (1) { read(1,buf,512); } } int main(char** argc, int argv) { pthread_t testthread1; struct sigaction action; action.sa_handler=sighandler; action.sa_flags=0; sigfillset( &action.sa_mask ); sigaction(SIGUSR1,&action,NULL); pthread_create(&testthread1,NULL,threadstart,NULL); while (1) { pthread_kill(testthread1,SIGUSR1); } } --MP_//2QRbacSOBFpiqJpH/m8fPe Content-Type: text/plain; charset=us-ascii -- Problem reports: http://cygwin.com/problems.html FAQ: http://cygwin.com/faq/ Documentation: http://cygwin.com/docs.html Unsubscribe info: http://cygwin.com/ml/#unsubscribe-simple --MP_//2QRbacSOBFpiqJpH/m8fPe--