Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 19 Dec 2000 18:56:14 +0100 (CET)
From:      tobez@tobez.org
To:        FreeBSD-gnats-submit@freebsd.org
Cc:        deischen@freebsd.org, jasone@freebsd.org
Subject:   bin/23647: libc_r: non-delivery of previously blocked signals
Message-ID:  <200012191756.eBJHuEv89695@aylee.t-d.rh.dk>
Resent-Message-ID: <200012191800.eBJI0BE38857@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help

>Number:         23647
>Category:       bin
>Synopsis:       libc_r: non-delivery of previously blocked signals
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Tue Dec 19 10:00:04 PST 2000
>Closed-Date:
>Last-Modified:
>Originator:     Anton Berezin
>Release:        FreeBSD 5.0-CURRENT i386
>Organization:
self
>Environment:

Relatively recent 5.0-CURRENT and 4.2-STABLE.

>Description:

In the program below the SIGINT signal should be delivered immediately
after SIGHUP handler returns.  This does not happen on recent -current
and -stable boxes.

The same program compiled with libc works fine.  It also works right on
3.5, 4.1.1 and older -current boxes.

It appears that pending signals are simply discarded in
_thread_sig_handle_pending() after thread_sig_find() being unable to
find the thread to deliver the signal due to the signal being blocked.

>How-To-Repeat:

Run the following program compiled with -pthread.  The expected output
is `:-)', any other output is wrong.

#include <sys/types.h>
#include <string.h>
#include <signal.h>
#include <stdio.h>
#include <unistd.h>

char sequence[64];
int seqi = 0;
int self;

void hupper(int s)
{
   sequence[seqi++] = ':';
   kill(self,SIGINT);
   sleep(2);
   sequence[seqi++] = '-';
}

void inter(int s)
{
   sequence[seqi++] = ')';
}

int main(void)
{
   struct sigaction sa;

   self = getpid();
   bzero(&sa, sizeof(sa));
   sa.sa_handler = hupper;
   sigaddset(&sa.sa_mask, SIGINT);
   sigaction(SIGHUP, &sa, NULL);
   signal(SIGINT, inter);
   kill(self,SIGHUP);
   sleep(1);
   sequence[seqi++] = '\0';
   printf("%s\n", sequence);
   return 0;
}

>Fix:

I am too unfamiliar with uthread code, so I am afraid the fix below a)
slows down _thread_kern_scheduler(); and b) might break some things.
Nevertheless, here is my take:

--- lib/libc_r/uthread/uthread_kern.c.orig	Tue Dec 19 18:19:19 2000
+++ lib/libc_r/uthread/uthread_kern.c	Tue Dec 19 18:28:37 2000
@@ -203,6 +203,11 @@ _thread_kern_scheduler(void)
 		_thread_sig_check_pending(_thread_run);
 	}
 
+	/* Handle any pending signals */
+	_queue_signals = 1;
+	dequeue_signals();
+	_queue_signals = 0;
+
 	/*
 	 * Enter a scheduling loop that finds the next thread that is
 	 * ready to run. This loop completes when there are no more threads
--- lib/libc_r/uthread/uthread_sig.orig	Tue Dec 19 18:19:31 2000
+++ lib/libc_r/uthread/uthread_sig.c	Tue Dec 19 18:26:21 2000
@@ -483,6 +483,14 @@ _thread_sig_handle_pending(void)
 					 */
 					thread_sig_add(pthread, sig,
 					    /*has_args*/ 1);
+				} else {
+					/*
+					 * We do not want to accidentally
+					 * loose the signal, will try to
+					 * handle it at some later time:
+					 */
+					_thread_sigq[i].blocked = 0;
+					_thread_sigq[i].pending = 1;
 				}
 			}
 		}


>Release-Note:
>Audit-Trail:
>Unformatted:


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-bugs" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200012191756.eBJHuEv89695>