X-Recipient: archive-cygwin AT delorie DOT com X-SWARE-Spam-Status: No, hits=0.3 required=5.0 tests=AWL,BAYES_00,T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org From: Manuel Wienand To: "cygwin AT cygwin DOT com" Date: Thu, 4 Nov 2010 13:49:32 +0100 Subject: Cygwin >= 1.7.7 Installing a signal handler causes system calls in other threads to get interrupted. Message-ID: <0C11C5BF0B29FD43A8D0250F711D497F7F6CC9DAF4@ex01-ubitronix.ubitronix.local> x-esetresult: clean, is OK x-esetid: 457DA920DB39A13C163D Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 X-IsSubscribed: yes 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 Hi, I have the following problem. When I install a signal handler and unblock t= he according signal in one thread, system calls in other threads will be in= terrupted, although the signal is blocked or ignored in those other threads. Regards, Manuel Btw: Thanks Corinna for the ultra fast bugfix last time. I just didn't want= to spam the list with this one line ;) ------------------------- Basic structure of the test case: Main: - Block signal X - Create thread 1 and 2 - Send signal X to thread 1 Thread 1: - Install signal handler for signal X - Unblock signal X Thread 2: - [Signal X is still blocked] - execute an interruptible system call. After sending signal X to thread 1, the system call in thread 2 will be int= errupted. Code of the test case: #include #include #include #include #include #include pthread_t DoNotInterruptThreadId1; pthread_t DoNotInterruptThreadId2; pthread_t UsesSignalThreadId; int createThread(void* (*fpStartRoutine)(void* ), void * arg, pthread_t * t= hreadId ) { int ret =3D 0; pthread_attr_t attr; ret =3D pthread_attr_init( &attr ); if( ret !=3D 0 ) { pthread_attr_destroy( &attr ); printf("pthread_attr_init() failed: %s %d\n",sys_errlist[ret],ret); return EXIT_FAILURE; } ret =3D pthread_create(threadId, &attr, fpStartRoutine, arg); if( ret !=3D 0 ) { pthread_attr_destroy( &attr ); printf("pthread_create failed: %s %d\n",sys_errlist[ret],ret); return EXIT_FAILURE; } pthread_attr_destroy( &attr ); return EXIT_SUCCESS; } static void SignalHandler(int signo) { int i =3D 0; i++; printf("---> Signalhandler called: "); switch (signo) { case SIGUSR1: { i++; // Some dummy code. printf("SIGUSR1.\n"); break; } default: printf("Unknown signal.\n"); break; } } void * DoNotInterruptThread(void * data) { sigset_t signal_mask; // Check, if the signal is still blocked. sigemptyset (&signal_mask); if (pthread_sigmask (SIG_BLOCK, NULL, &signal_mask) !=3D 0) { printf("DoNotInterruptThread: Failed to check signal state.\n"); return (void*)EXIT_FAILURE; } if (sigismember(&signal_mask, SIGUSR1) !=3D 1) { printf("DoNotInterruptThread: SIGUSR1 not blocked.\n"); } else { printf("DoNotInterruptThread: SIGUSR1 blocked.\n"); } while(1) { if (sleep(1) !=3D 0) { printf("DoNotInterruptThread: Sleep failed: %s %d\n",sys_errlist[errno= ],errno); return (void*)EXIT_FAILURE; } #if 0 // Send signal, nothing should happen... printf("DoNotInterruptThread: Starting to send SIGUSR1 to self.\n"); int err =3D 0; err =3D pthread_kill(pthread_self(), SIGUSR1); if (err !=3D 0) { printf("DoNotInterruptThread: Sending SIGUSR1 to self...failed.\n"); return (void*)EXIT_FAILURE; } #endif } } void * UsesSignalThread(void * data) { sigset_t signal_mask; struct sigaction sa; // Check, if the signal is still blocked. sigemptyset (&signal_mask); if (pthread_sigmask (SIG_BLOCK, NULL, &signal_mask) !=3D 0) { printf("UsesSignalThread: Failed to check signal state.\n"); return (void*)EXIT_FAILURE; } if (sigismember(&signal_mask, SIGUSR1) !=3D 1) { printf("UsesSignalThread: SIGUSR1 not blocked (error).\n"); } else { printf("UsesSignalThread: SIGUSR1 blocked (as expected).\n"); } // Install signal handler memset(&sa, 0, sizeof(sa)); sa.sa_handler =3D SignalHandler; sigemptyset(&sa.sa_mask); // Don't block other signals while in the signa= l handler function //sa.sa_flags =3D SA_RESTART; // Restart functions if interrupted by hand= ler if (sigaction(SIGUSR1, &sa, NULL) =3D=3D -1) // NULL =3D don't return the= previous installed signal action. { printf("UsesSignalThread: Failed to install signal handler.\n"); return (void*)EXIT_FAILURE; } else { printf("UsesSignalThread: Successfully installed signal handler.\n"); } // Unblock the signal to be able to enter the signal handler. sigemptyset (&signal_mask); sigaddset (&signal_mask, SIGUSR1); if (pthread_sigmask (SIG_UNBLOCK, &signal_mask, NULL) !=3D 0) { printf("UsesSignalThread: Failed to unblock signal.\n"); return (void*)EXIT_FAILURE; } else { printf("UsesSignalThread: Successfully unblocked signal.\n"); } // Wait some time. if (sleep(2) !=3D 0) { printf("UsesSignalThread: Sleep failed: %s %d\n",sys_errlist[errno],err= no); } return (void*)EXIT_SUCCESS; } int main(void) { sigset_t signal_mask; puts("Starting Signal test."); // Block SIGUSR1 in this thread and thus in all threads created after thi= s point. // Those threads which need the signal will unblock it for themselves. sigemptyset (&signal_mask); sigaddset (&signal_mask, SIGUSR1); if (pthread_sigmask (SIG_BLOCK, &signal_mask, NULL) !=3D 0) { printf("pthread_sigmask() failed.\n"); return EXIT_FAILURE; } // Create 2 two threads which shall not be interrupted by SIGUSR1. if (createThread(DoNotInterruptThread, NULL, &DoNotInterruptThreadId1) != =3D EXIT_SUCCESS) { printf("Failed to create DoNotInterrupt 1.\n"); } if (createThread(DoNotInterruptThread, NULL, &DoNotInterruptThreadId2) != =3D EXIT_SUCCESS) { printf("Failed to create DoNotInterrupt 2.\n"); } // Create a thread which uses a signal handler to handle SIGUSR1. if (createThread(UsesSignalThread, NULL, &UsesSignalThreadId) !=3D EXIT_S= UCCESS) { printf("Failed to create UsesSignalThread.\n"); } sleep(1); // Sleep one second printf("Main: Starting to send SIGUSR1.\n"); int err =3D 0; err =3D pthread_kill(UsesSignalThreadId, SIGUSR1); if (err !=3D 0) { printf("Main: Sending SIGUSR1...failed.\n"); return EXIT_FAILURE; } printf("Main: Sending SIGUSR1...success.\n"); pthread_join(UsesSignalThreadId, NULL); return EXIT_SUCCESS; } -- 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