threads/72953: fork() unblocks blocked signals w/o PTHREAD_SCOPE_SYSTEM

Mark Andrews marka at daemon.lab.isc.org
Thu Oct 21 00:00:49 PDT 2004


>Number:         72953
>Category:       threads
>Synopsis:       fork() unblocks blocked signals w/o PTHREAD_SCOPE_SYSTEM
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    freebsd-threads
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Thu Oct 21 07:00:44 GMT 2004
>Closed-Date:
>Last-Modified:
>Originator:     Mark Andrews
>Release:        FreeBSD 5.3-BETA6 i386
>Organization:
ISC
>Environment:
System: FreeBSD daemon.lab.isc.org 5.3-BETA6 FreeBSD 5.3-BETA6 #16: Tue Oct 5 23:37:23 UTC 2004 jinmei at daemon.lab.isc.org:/hog0/users/jinmei/src/sys/i386/compile/DAEMON i386


>Description:

	fork() clears blocked signals unless PTHREAD_SCOPE_SYSTEM is set.
	
>How-To-Repeat:

	Run the following program with and without the arguement system.
	In the first case the program will incorrectly be killed by the
	SIGTERM.  In the second case the signal will be blocked and
	sigwait returns.

#include <pthread.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <signal.h>
#include <stdlib.h>

sigset_t signal_mask;

void
dofork() {
	switch (fork()) {
	case 0:
		break;
	case -1:
		_exit(1);
	default:
		_exit(0);
	}
	fprintf(stderr, "fork\n");
	fflush(stderr);
}

static void *
waiter(void *arg) {
        int result;
        int sig;

        result = sigwait(&signal_mask, &sig);
        if (result != 0)
                fprintf(stderr, "sigwait: %\n", strerror(result));
        else
                fprintf(stderr, "signal %d\n", sig);
	fflush(stderr);
        return (NULL);
}

int
main(int argc, char **argv) {
        pthread_t id;
	pthread_attr_t attr;
        int result;
	int scope = 0;

        if (argc > 1) {
                if (strcmp(argv[1], "system") == 0)
                        scope = 1;
        }

        sigemptyset (&signal_mask);
        sigaddset (&signal_mask, SIGTERM);

        result = pthread_sigmask(SIG_BLOCK, &signal_mask, NULL);
        if (result != 0)
                fprintf(stderr, "pthread_sigmask: %\n", strerror(result));
        else
                fprintf(stderr, "pthread_sigmask: OK\n");
	fflush(stderr);

	dofork();

	result = pthread_attr_init(&attr);
        if (result != 0)
                fprintf(stderr, "pthread_attr_init: %\n", strerror(result));
        else
                fprintf(stderr, "pthread_attr_init: OK\n");
	fflush(stderr);
	
	if (scope) {
		result = pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);
		if (result != 0)
			fprintf(stderr, "pthread_attr_setscope: %\n",
				strerror(result));
		else
			fprintf(stderr, "pthread_attr_setscope: OK\n");
	} else
		fprintf(stderr, "default scope\n");
	fflush(stderr);

        result = pthread_create (&id, &attr, waiter, NULL);
        if (result != 0)
                fprintf(stderr, "pthread_create: %\n", strerror(result));
        else
                fprintf(stderr, "pthread_create: OK\n");
	fflush(stderr);
        if (kill(getpid(), SIGTERM) == -1)
                perror("kill");
        else
                fprintf(stderr, "kill: OK\n");
	fflush(stderr);
        result = pthread_join(id, NULL);
        if (result != 0)
                fprintf(stderr, "pthread_join: %\n", strerror(result));
        else
                fprintf(stderr, "pthread_join: OK\n");
	fflush(stderr);
        return(0);
}

>Fix:

	


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


More information about the freebsd-threads mailing list