Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
[BZ #1951]
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.
  • Loading branch information
Ulrich Drepper committed Apr 23, 2006
1 parent 9055724 commit 727a683
Show file tree
Hide file tree
Showing 4 changed files with 211 additions and 9 deletions.
8 changes: 8 additions & 0 deletions ChangeLog
@@ -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
Expand Down
5 changes: 2 additions & 3 deletions signal/Makefile
@@ -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
Expand Down Expand Up @@ -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

Expand Down
184 changes: 184 additions & 0 deletions signal/tst-sigset2.c
@@ -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 */
23 changes: 17 additions & 6 deletions sysdeps/posix/sigset.c
@@ -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
Expand Down Expand Up @@ -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. */
Expand All @@ -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 */

Expand All @@ -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;
}

0 comments on commit 727a683

Please sign in to comment.