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/