Bug 17757 - select returns 0 if pthread_kill'd w/ sig. handler
Summary: select returns 0 if pthread_kill'd w/ sig. handler
Status: Closed FIXED
Alias: None
Product: Base System
Classification: Unclassified
Component: kern (show other bugs)
Version: 4.0-STABLE
Hardware: Any Any
: Normal Affects Only Me
Assignee: Daniel Eischen
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2000-04-02 20:50 UTC by Thimble Smith
Modified: 2000-11-18 00:09 UTC (History)
0 users

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Thimble Smith 2000-04-02 20:50:02 UTC
When a thread installs a signal handler, and then is pthread_kill'd
during a select, it returns 0 (as if the select timed out) instead of
-1.  In addition, errno is not set to EINTR.

If a signal handler is not installed, select correctly returns -1 and
sets errno to EINTR.

I'm not sure if this affects reads and writes or not, yet.

How-To-Repeat: 
cd /tmp

cat <<END_PROG > simple.c
#include <errno.h>
#include <pthread.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

void *t_body(void *arg);

pthread_mutex_t t_lock;
pthread_cond_t  t_cond;
sigset_t        set;

#define WRITE(x) do { printf(x "\n"); fflush(stdout); } while (0)

int
main(void)
{
        pthread_t t;

        WRITE("main: hello");

        pthread_mutex_init(&t_lock, NULL);
        pthread_cond_init(&t_cond, NULL);
        sigemptyset(&set);
        sigaddset(&set, SIGUSR1);

        pthread_mutex_lock(&t_lock);
        WRITE("main: creating test thread...");
        pthread_create(&t, NULL, t_body, NULL);
        pthread_cond_wait(&t_cond, &t_lock);
        pthread_mutex_unlock(&t_lock);

        pthread_sigmask(SIG_BLOCK, &set, NULL);

        sleep(1);

        WRITE("main: killing test thread");
        pthread_kill(t, SIGUSR1);

        pthread_exit(NULL);

        /* NOTREACHED */
        exit(EXIT_SUCCESS);
}

void
handle_sigusr1(int sig)
{
        WRITE("handle_sigusr1");
        signal(sig, handle_sigusr1);
}

void *
t_body(void *arg)
{
        struct sigaction sact;
        fd_set fds;
        int error;

        WRITE("test: hello");

#ifdef SIG
        sact.sa_flags   = 0;
        sact.sa_handler = handle_sigusr1;
        sigaction(SIGUSR1, &sact, NULL);
#endif

        FD_ZERO(&fds);

        pthread_detach(pthread_self());
        pthread_sigmask(SIG_UNBLOCK, &set, NULL);

        WRITE("test: go ahead, main");

        pthread_mutex_lock(&t_lock);
        pthread_cond_signal(&t_cond);
        pthread_mutex_unlock(&t_lock);

        WRITE("test: sleeping...");
        error = select(0, &fds, 0, 0, 0);

        printf("test: select returned %d\n", error); fflush(stdout);
        if (errno == EINTR)
                WRITE("test: INTERRUPTED!  Yeah!");
        else {
                printf("test: uh-oh (error: %s)\n", strerror(errno));
                fflush(stdout);
        }

        return NULL;
}

END_PROG

cc -o simple -DSIG simple.c -pthread
./simple
cc -o simple simple.c -pthread
./simple
Comment 1 Sheldon Hearn freebsd_committer freebsd_triage 2000-04-03 13:27:12 UTC
Responsible Changed
From-To: freebsd-bugs->jasone

Over to our threads guy. 
Comment 2 Daniel Eischen freebsd_committer freebsd_triage 2000-09-04 14:35:44 UTC
Responsible Changed
From-To: jasone->deischen

I've got some changes to the threads library in the pipeline 
and have this problem fixed.
Comment 3 Daniel Eischen freebsd_committer freebsd_triage 2000-11-18 00:07:28 UTC
State Changed
From-To: open->closed

This is fixed in both -current and -stable.  There was one flaw 
in this PR, though.  If a signal handler is not installed, then 
the signal gets sent to the process.  For the test case included 
here, that means that the program will get killed by SIGUSR1.