On Wed, 12 Oct 2005, Pavel Tsekov wrote:

> On Tue, 11 Oct 2005, Christopher Faylor wrote:
>
> > I don't see how ignoring blocked signals would cause a SEGV however.
>
> Well... indirectly they do :) I hope you are not too annoyed already
> because this time I really found the cause of the problem.
>
> Assume a signal is sent to a thread with pthread_kill() but the thread is
> blocking the signal and in doesn't get processed through it's lifetime.
> The thread dies but the signal still remains in the singal queue.
> Something triggeres the processing of the signal - sig_dispatch_pending()
> in my case (which is called as part of pthread_sigmask()). As part of the
> processing the 'tls' member of sigpacket is dereferenced but at that time
> it is already invalid.
>
> I'll try to post a testcase ASAP which demonstrates the problem.

Find the testcase attached. The interesting part starts when SIGUSR2 is
send from the main thread.
#include <limits.h>
#include <signal.h>
#include <stdio.h>
#include <pthread.h>

static pid_t the_pid;

static void empty_handler(int signo)
{
  printf ("in empty_handler(): signo = %d\n", signo);
}

static void *thread_loop (void *unused)
{
  int i;
  sigset_t block_set, pending_set;

  sigemptyset (&block_set);
  sigaddset (&block_set, SIGUSR2);
  if (pthread_sigmask (SIG_BLOCK, &block_set, NULL) != 0)
    {
      printf ("failed to set the list of blocked signals\n");
    }

  /* All done - let the main thread know that it
     can send us a signal. */
  kill (the_pid, SIGUSR1);

  for (i = 0; i < INT_MAX; i++);

  printf ("exiting thread_loop()\n");

  return NULL;
}

int main (int argc, char **argv)
{
  int rv;
  int i;
  pthread_t thr_id;
  sigset_t new_set, old_set;
  void *thr_result;

  the_pid = getpid ();

  /* Dummy synchronization scheme so that we know that
     the second thread initialized its list of blocked
     signals. */
  signal (SIGUSR1, empty_handler);
  sigemptyset (&new_set);
  sigaddset (&new_set, SIGUSR1);
  sigprocmask (SIG_BLOCK, &new_set, &old_set);

  rv = pthread_create (&thr_id, NULL, thread_loop, NULL);
  if (rv != 0)
    {
      printf ("failed to create thread.\n");
      exit (1);
    }

  /* Wait until the second thread signals the main thread. */
  sigsuspend (&old_set);
  sigprocmask (SIG_UNBLOCK, &new_set, NULL);

  /* Send a SIGUSR2 signal to the second thread while
     it is blocking SIGUSR2. */
  pthread_kill (thr_id, SIGUSR2);

  /* Wait for the thread to terminate. */
  pthread_join (thr_id, &thr_result);

  /* Trigger sig_dispatch_pending() */
  signal (SIGUSR1, SIG_IGN);

  /* Just wait for the program to crash. */
  sleep (600);

  exit (0);
}
--
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple
Problem reports:       http://cygwin.com/problems.html
Documentation:         http://cygwin.com/docs.html
FAQ:                   http://cygwin.com/faq/

Reply via email to