Hi,

any suggestions? Can anyone confirm the problem (at least for me the behavior 
is unexpected...)?

Regards,

Manuel


-----Last message-----

Hi,

I have the following problem. When I install a signal handler and unblock the 
according signal in one thread, system calls in other threads will be 
interrupted, 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 
interrupted.

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 * 
threadId )
{
  int ret = 0;
  pthread_attr_t attr;

  ret = pthread_attr_init( &attr );
  if( ret != 0 )
  {
    pthread_attr_destroy( &attr );
    printf("pthread_attr_init() failed: %s %d\n",sys_errlist[ret],ret);
    return EXIT_FAILURE;
  }

  ret = pthread_create(threadId, &attr, fpStartRoutine, arg);
  if( ret != 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 = 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) != 0)
  {
    printf("DoNotInterruptThread: Failed to check signal state.\n");
    return (void*)EXIT_FAILURE;
  }

  if (sigismember(&signal_mask, SIGUSR1) != 1)
  {
    printf("DoNotInterruptThread: SIGUSR1 not blocked.\n");
  }
  else
  {
    printf("DoNotInterruptThread: SIGUSR1 blocked.\n");
  }

  while(1)
  {
   if (sleep(1) != 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 = 0;
   err = pthread_kill(pthread_self(), SIGUSR1);
   if (err != 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) != 0)
  {
    printf("UsesSignalThread: Failed to check signal state.\n");
    return (void*)EXIT_FAILURE;
  }

  if (sigismember(&signal_mask, SIGUSR1) != 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 = SignalHandler;
  sigemptyset(&sa.sa_mask); // Don't block other signals while in the signal 
handler function
  //sa.sa_flags = SA_RESTART; // Restart functions if interrupted by handler
  if (sigaction(SIGUSR1, &sa, NULL) == -1) // NULL = 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) != 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) != 0)
  {
    printf("UsesSignalThread: Sleep failed: %s %d\n",sys_errlist[errno],errno);
  }
  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 this 
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) != 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) != 
EXIT_SUCCESS)
  {
    printf("Failed to create DoNotInterrupt 1.\n");
  }
  if (createThread(DoNotInterruptThread, NULL, &DoNotInterruptThreadId2) != 
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) != EXIT_SUCCESS)
  {
    printf("Failed to create UsesSignalThread.\n");
  }

  sleep(1); // Sleep one second

  printf("Main: Starting to send SIGUSR1.\n");
  int err = 0;
  err = pthread_kill(UsesSignalThreadId, SIGUSR1);
  if (err != 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


-- 
This message has been scanned for viruses and
dangerous content by MailScanner, and is
believed to be clean.


--
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

Reply via email to