2006-04-23  Ulrich Drepper  <drepper@redhat.com>
	[BZ #1951]
	* sysdeps/posix/sigset.c (sigset): Return correct value reflecting
	previous signal state.
	* signal/Makefile (tests): Add tst-sigset2.
	* signal/tst-sigset2.c: New file.
This commit is contained in:
Ulrich Drepper 2006-04-23 19:05:33 +00:00
parent 9055724a92
commit 727a6832f0
4 changed files with 211 additions and 9 deletions

View file

@ -1,3 +1,11 @@
2006-04-23 Ulrich Drepper <drepper@redhat.com>
[BZ #1951]
* sysdeps/posix/sigset.c (sigset): Return correct value reflecting
previous signal state.
* signal/Makefile (tests): Add tst-sigset2.
* signal/tst-sigset2.c: New file.
2006-04-21 Jakub Jelinek <jakub@redhat.com>
* argp/argp.h (__option_is_short): Check upper limit of

View file

@ -1,5 +1,4 @@
# Copyright (C) 1991,1992,1993,1994,1995,1996,1997,1998,2003
# Free Software Foundation, Inc.
# Copyright (C) 1991-1998,2003,2006 Free Software Foundation, Inc.
# This file is part of the GNU C Library.
# The GNU C Library is free software; you can redistribute it and/or
@ -38,7 +37,7 @@ routines := signal raise killpg \
allocrtsig sigtimedwait sigwaitinfo sigqueue \
sighold sigrelse sigignore sigset
tests := tst-signal tst-sigset tst-sigsimple tst-raise
tests := tst-signal tst-sigset tst-sigsimple tst-raise tst-sigset2
distribute := sigsetops.h testrtsig.h sigset-cvt-mask.h

184
signal/tst-sigset2.c Normal file
View file

@ -0,0 +1,184 @@
/* sigset_SIG_HOLD_bug.c [BZ #1951] */
#include <errno.h>
#include <error.h>
#include <inttypes.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#define TEST_SIG SIGINT
/* Print mask of blocked signals for this process */
static void
printSigMask (const char *msg)
{
sigset_t currMask;
int sig;
int cnt;
if (msg != NULL)
printf ("%s", msg);
if (sigprocmask (SIG_BLOCK, NULL, &currMask) == -1)
error (1, errno, "sigaction");
cnt = 0;
for (sig = 1; sig < NSIG; sig++)
{
if (sigismember (&currMask, sig))
{
cnt++;
printf ("\t\t%d (%s)\n", sig, strsignal (sig));
}
}
if (cnt == 0)
printf ("\t\t<empty signal set>\n");
} /* printSigMask */
static void
handler (int sig)
{
printf ("Caught signal %d\n", sig);
printSigMask ("Signal mask in handler\n");
printf ("Handler returning\n");
_exit (1);
} /* handler */
static void
printDisposition (sighandler_t disp)
{
if (disp == SIG_HOLD)
printf ("SIG_HOLD");
else if (disp == SIG_DFL)
printf ("SIG_DFL");
else if (disp == SIG_IGN)
printf ("SIG_IGN");
else
printf ("handled at %" PRIxPTR, (uintptr_t) disp);
} /* printDisposition */
static int
returnTest1 (void)
{
sighandler_t prev;
printf ("===== TEST 1 =====\n");
printf ("Blocking signal with sighold()\n");
if (sighold (TEST_SIG) == -1)
error (1, errno, "sighold");
printSigMask ("Signal mask after sighold()\n");
printf ("About to use sigset() to establish handler\n");
prev = sigset (TEST_SIG, handler);
if (prev == SIG_ERR)
error(1, errno, "sigset");
printf ("Previous disposition: ");
printDisposition (prev);
printf (" (should be SIG_HOLD)\n");
if (prev != SIG_HOLD)
{
printf("TEST FAILED!!!\n");
return 1;
}
return 0;
} /* returnTest1 */
static int
returnTest2 (void)
{
sighandler_t prev;
printf ("\n===== TEST 2 =====\n");
printf ("About to use sigset() to set SIG_HOLD\n");
prev = sigset (TEST_SIG, SIG_HOLD);
if (prev == SIG_ERR)
error (1, errno, "sigset");
printf ("Previous disposition: ");
printDisposition (prev);
printf (" (should be SIG_DFL)\n");
if (prev != SIG_DFL)
{
printf("TEST FAILED!!!\n");
return 1;
}
return 0;
} /* returnTest2 */
static int
returnTest3 (void)
{
sighandler_t prev;
printf ("\n===== TEST 3 =====\n");
printf ("About to use sigset() to set SIG_HOLD\n");
prev = sigset (TEST_SIG, SIG_HOLD);
if (prev == SIG_ERR)
error (1, errno, "sigset");
printf ("About to use sigset() to set SIG_HOLD (again)\n");
prev = sigset (TEST_SIG, SIG_HOLD);
if (prev == SIG_ERR)
error (1, errno, "sigset");
printf ("Previous disposition: ");
printDisposition (prev);
printf (" (should be SIG_HOLD)\n");
if (prev != SIG_HOLD)
{
printf("TEST FAILED!!!\n");
return 1;
}
return 0;
} /* returnTest3 */
int
main (int argc, char *argv[])
{
pid_t childPid;
childPid = fork();
if (childPid == -1)
error (1, errno, "fork");
if (childPid == 0)
exit (returnTest1 ());
int status;
if (TEMP_FAILURE_RETRY (waitpid (childPid, &status, 0)) != childPid)
error (1, errno, "waitpid");
int result = !WIFEXITED (status) || WEXITSTATUS (status) != 0;
childPid = fork();
if (childPid == -1)
error (1, errno, "fork");
if (childPid == 0)
exit (returnTest2 ());
if (TEMP_FAILURE_RETRY (waitpid (childPid, &status, 0)) != childPid)
error (1, errno, "waitpid");
result |= !WIFEXITED (status) || WEXITSTATUS (status) != 0;
childPid = fork();
if (childPid == -1)
error (1, errno, "fork");
if (childPid == 0)
exit (returnTest3 ());
if (TEMP_FAILURE_RETRY (waitpid (childPid, &status, 0)) != childPid)
error (1, errno, "waitpid");
result |= !WIFEXITED (status) || WEXITSTATUS (status) != 0;
return result;
} /* main */

View file

@ -1,4 +1,4 @@
/* Copyright (C) 1998, 2000, 2005 Free Software Foundation, Inc.
/* Copyright (C) 1998, 2000, 2005, 2006 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@ -29,8 +29,10 @@ sigset (sig, disp)
int sig;
__sighandler_t disp;
{
struct sigaction act, oact;
struct sigaction act;
struct sigaction oact;
sigset_t set;
sigset_t oset;
#ifdef SIG_HOLD
/* Handle SIG_HOLD first. */
@ -45,10 +47,18 @@ sigset (sig, disp)
return SIG_ERR;
/* Add the signal set to the current signal mask. */
if (__sigprocmask (SIG_BLOCK, &set, NULL) < 0)
if (__sigprocmask (SIG_BLOCK, &set, &oset) < 0)
return SIG_ERR;
return SIG_HOLD;
/* If the signal was already blocked signal this to the caller. */
if (__sigismember (&oset, sig))
return SIG_HOLD;
/* We need to determine whether a specific handler is installed. */
if (__sigaction (sig, NULL, &oact) < 0)
return SIG_ERR;
return oact.sa_handler;
}
#endif /* SIG_HOLD */
@ -75,8 +85,9 @@ sigset (sig, disp)
return SIG_ERR;
/* Remove the signal set from the current signal mask. */
if (__sigprocmask (SIG_UNBLOCK, &set, NULL) < 0)
if (__sigprocmask (SIG_UNBLOCK, &set, &oset) < 0)
return SIG_ERR;
return oact.sa_handler;
/* If the signal was already blocked return SIG_HOLD. */
return __sigismember (&oset, sig) ? SIG_HOLD : oact.sa_handler;
}