Mail Archives: cygwin/2010/11/04/08:52:46
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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <pthread.h>
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
- Raw text -