This is the mail archive of the mailing list for the glibc project.

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Bug#159899: libc6: sem_wait is not interrupted by signals, as required by SuS

   Zack Weinberg posted this as a debian bug report rather than here for
some reason. I thought you might want to see this in case it should be
addressed for glibc 2.3...

Package: libc6
Version: 2.2.5-14
Severity: normal
Tags: upstream

The Single Unix standard requires sem_wait() to be
interrupted by a signal delivered to the process - see for
details.  The glibc implementation of sem_wait(), however, continues
to wait on the semaphore after the signal is delivered.

To demonstrate this, I have appended a test program.  Compile
with -pthread and run it; it will block forever, and be unresponsive
to ^C (^\ will kill it).  On a Solaris machine, by contrast, it exits
successfully, printing nothing, after a short delay (due to the
nanosleep() call in child_thread).

Code inspection suggests this is still a bug in the latest glibc CVS.

-- System Information:
Debian Release: testing/unstable
Architecture: i386
Kernel: Linux egil 2.4.19 #1 Thu Aug 15 11:07:52 PDT 2002 i686
Locale: LANG=en_US, LC_CTYPE=en_US

-- test program:

#include <sys/types.h>
#include <errno.h>
#include <pthread.h>
#include <semaphore.h>
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <unistd.h>

static pid_t me;
static sem_t sema;
static volatile sig_atomic_t sigint_caught = 0;

static void *
child_thread(void *unused)
    sigset_t all;
    struct timespec ts;

    /* Block all signals in this thread.  */
    sigprocmask(SIG_SETMASK, &all, 0);

    /* Wait a moment to be sure the main thread is blocked on the
       semaphore.  */
    ts.tv_sec = 1;
    ts.tv_nsec = 0;
    nanosleep(&ts, 0);

    /* Now feed the main thread a signal.  This should interrupt
       execution of sem_wait().  */
    kill(me, SIGINT);

    return 0;

static void
sigint_handler(int unused)
    sigint_caught = 1;

    sigset_t none;
    pthread_t child;
    struct sigaction sa;
    int status;
    int semv;

    /* Initialize...  */
    me = getpid();
    sem_init(&sema, 0, 0);  /* semaphore starts out locked */
    sigprocmask(SIG_SETMASK, &none, 0);

    sa.sa_handler = sigint_handler;
    sa.sa_flags = 0;
    sigaction(SIGINT, &sa, 0);

    /* Spawn child thread.  */
    pthread_create(&child, 0, child_thread, 0);

    /* Block on semaphore.  This should be interrupted by the
       child sending us a signal.  */
    status = sem_wait(&sema);

    /* status should be -1, errno should be EINTR, sigint_caught
       should be 1, and the semaphore value should still be zero.  */
    if(status != -1)
	printf("status = %d != -1\n", status);
    if(errno != EINTR)
	printf("errno = %s != EINTR\n", strerror(errno));
    if(sigint_caught != 1)
	printf("sigint_caught = %d != 1\n", sigint_caught);
    sem_getvalue (&sema, &semv);
    if(semv != 0)
	printf("semv = %d != 0\n", semv);

    /* cleanup */
    pthread_join(child, 0);
    return 0;

I can reproduce this bug under glibc 2.2.93 with the program blocking

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]