I have noticed that sigwait() does not return immediately if called in
the following situation:
* One of the signals the command is looking for isalready pending.
* This signal was send to the entire process rather than to a specific
thread.
* sigwait() is called from a thread other than the 'main' thread.

Look at the test case below. The function test_sigwait() is first called
from the 'main' thread and then from another thread created in main().
This should not make a difference here, but the function shows different
behaviour.

My interpretation is that sigwait() simply forgets to look for
non-thread-specific signals which are already pending at the time when
it is called.

Regards,
Andreas

My system is:
$ uname -a
CYGWIN_NT-6.1-WOW64 zoppo 1.7.17(0.262/5/3) 2012-10-19 14:39 i686 Cygwin

Here is an example session (comments preceded by //):
$ ./test_case
pid: 2396
thread 1 waiting for SIGUSR1

// From another console, first send SIGUSR2
// (which should remain pending), then SIGUSR1:
$ kill -SIGUSR2 2396
$ kill -SIGUSR1 2396

// The program catches SIGUSR1 first, then SIGUSR2.
// Finally, a second thread starts waiting for SIGUSR1:
thread 1 received SIGUSR1
thread 1 waiting for SIGUSR2
thread 1 received SIGUSR2
thread 2 waiting for SIGUSR1

// Now the same again: first SIGUSR2, then SIGUSR1:
$ kill -SIGUSR2 2396
$ kill -SIGUSR1 2396

// The program only catches SIGUSR1,
// but it blocks waiting for SIGUSR2:
thread 2 received SIGUSR1
thread 2 waiting for SIGUSR2

// Send SIGUSR2 again:
$ kill -SIGUSR2 2396

// The program exits normally:
thread 2 received SIGUSR2
$

########################################
#include <stdio.h>
#include <signal.h>
#include <pthread.h>   // compile with -lpthread

void *test_sigwait(void *arg)
{
  int *threadnr = (int *)arg;
  int signr;
  sigset_t sigusr1, sigusr2;
  sigemptyset(&sigusr1);
  sigemptyset(&sigusr2);
  sigaddset(&sigusr1, SIGUSR1);
  sigaddset(&sigusr2, SIGUSR2);

  printf("thread %d waiting for SIGUSR1\n", *threadnr);
  sigwait(&sigusr1, &signr);
  printf("thread %d received SIGUSR1\n", *threadnr);

  printf("thread %d waiting for SIGUSR2\n", *threadnr);
  sigwait(&sigusr2, &signr);
  printf("thread %d received SIGUSR2\n", *threadnr);
}

int main()
{
  sigset_t sigmask;
  sigemptyset(&sigmask);
  sigaddset(&sigmask, SIGUSR1);
  sigaddset(&sigmask, SIGUSR2);
  sigprocmask(SIG_BLOCK, &sigmask, NULL);

  printf("pid: %d\n", getpid());

  int threadnr = 1;
  test_sigwait(&threadnr);

  pthread_t thread2;
  threadnr = 2;
  pthread_create(&thread2, NULL, test_sigwait, &threadnr);

  pthread_join(thread2, NULL);
  return(0);
}

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