mirror of https://gitee.com/Nocallback/glibc.git
committed by
Andreas Krebbel
8 changed files with 264 additions and 30 deletions
@ -0,0 +1,230 @@ |
|||
/* Testcase checks, if setcontext(), swapcontext() restores signal-mask
|
|||
and if pending signals are delivered after those calls. |
|||
Copyright (C) 2015 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 |
|||
modify it under the terms of the GNU Lesser General Public |
|||
License as published by the Free Software Foundation; either |
|||
version 2.1 of the License, or (at your option) any later version. |
|||
|
|||
The GNU C Library is distributed in the hope that it will be useful, |
|||
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|||
Lesser General Public License for more details. |
|||
|
|||
You should have received a copy of the GNU Lesser General Public |
|||
License along with the GNU C Library; if not, see |
|||
<http://www.gnu.org/licenses/>. */
|
|||
|
|||
#include <stdio.h> |
|||
#include <stdlib.h> |
|||
#include <sys/types.h> |
|||
#include <signal.h> |
|||
#include <ucontext.h> |
|||
#include <unistd.h> |
|||
|
|||
volatile int global; |
|||
volatile sig_atomic_t handlerCalled; |
|||
|
|||
static void |
|||
check (const char *funcName) |
|||
{ |
|||
sigset_t set; |
|||
|
|||
/* check if SIGUSR2 is unblocked after setcontext-call. */ |
|||
sigprocmask (SIG_BLOCK, NULL, &set); |
|||
|
|||
if (sigismember (&set, SIGUSR2) != 0) |
|||
{ |
|||
printf ("FAIL: SIGUSR2 is blocked after %s.\n", funcName); |
|||
exit (1); |
|||
} |
|||
|
|||
if (sigismember (&set, SIGUSR1) != 1) |
|||
{ |
|||
printf ("FAIL: SIGUSR1 is not blocked after %s.\n", funcName); |
|||
exit (1); |
|||
} |
|||
} |
|||
|
|||
static void |
|||
signalmask (int how, int signum) |
|||
{ |
|||
sigset_t set; |
|||
sigemptyset (&set); |
|||
sigaddset (&set, signum); |
|||
if (sigprocmask (how, &set, NULL) != 0) |
|||
{ |
|||
printf ("FAIL: sigprocmaks (%d, %d, NULL): %m\n", how, signum); |
|||
exit (1); |
|||
} |
|||
} |
|||
|
|||
static void |
|||
signalpending (int signum, const char *msg) |
|||
{ |
|||
sigset_t set; |
|||
sigemptyset (&set); |
|||
if (sigpending (&set) != 0) |
|||
{ |
|||
printf ("FAIL: sigpending: %m\n"); |
|||
exit (1); |
|||
} |
|||
if (sigismember (&set, SIGUSR2) != 1) |
|||
{ |
|||
printf ("FAIL: Signal %d is not pending %s\n", signum, msg); |
|||
exit (1); |
|||
} |
|||
} |
|||
|
|||
static void |
|||
handler (int __attribute__ ((unused)) signum) |
|||
{ |
|||
handlerCalled ++; |
|||
} |
|||
|
|||
static int |
|||
do_test (void) |
|||
{ |
|||
ucontext_t ctx, oldctx; |
|||
struct sigaction action; |
|||
pid_t pid; |
|||
|
|||
pid = getpid (); |
|||
|
|||
/* unblock SIGUSR2 */ |
|||
signalmask (SIG_UNBLOCK, SIGUSR2); |
|||
|
|||
/* block SIGUSR1 */ |
|||
signalmask (SIG_BLOCK, SIGUSR1); |
|||
|
|||
/* register handler for SIGUSR2 */ |
|||
action.sa_flags = 0; |
|||
action.sa_handler = handler; |
|||
sigemptyset (&action.sa_mask); |
|||
sigaction (SIGUSR2, &action, NULL); |
|||
|
|||
if (getcontext (&ctx) != 0) |
|||
{ |
|||
printf ("FAIL: getcontext: %m\n"); |
|||
exit (1); |
|||
} |
|||
|
|||
global++; |
|||
|
|||
if (global == 1) |
|||
{ |
|||
puts ("after getcontext"); |
|||
|
|||
/* block SIGUSR2 */ |
|||
signalmask (SIG_BLOCK, SIGUSR2); |
|||
|
|||
/* send SIGUSR2 to me */ |
|||
handlerCalled = 0; |
|||
kill (pid, SIGUSR2); |
|||
|
|||
/* was SIGUSR2 handler called? */ |
|||
if (handlerCalled != 0) |
|||
{ |
|||
puts ("FAIL: signal handler was called, but signal was blocked."); |
|||
exit (1); |
|||
} |
|||
|
|||
/* is SIGUSR2 pending? */ |
|||
signalpending (SIGUSR2, "before setcontext"); |
|||
|
|||
/* SIGUSR2 will be unblocked by setcontext-call. */ |
|||
if (setcontext (&ctx) != 0) |
|||
{ |
|||
printf ("FAIL: setcontext: %m\n"); |
|||
exit (1); |
|||
} |
|||
} |
|||
else if (global == 2) |
|||
{ |
|||
puts ("after setcontext"); |
|||
|
|||
/* check SIGUSR1/2 */ |
|||
check ("setcontext"); |
|||
|
|||
/* was SIGUSR2 handler called? */ |
|||
if (handlerCalled != 1) |
|||
{ |
|||
puts ("FAIL: signal handler was not called after setcontext."); |
|||
exit (1); |
|||
} |
|||
|
|||
/* block SIGUSR2 */ |
|||
signalmask (SIG_BLOCK, SIGUSR2); |
|||
|
|||
/* send SIGUSR2 to me */ |
|||
handlerCalled = 0; |
|||
kill (pid, SIGUSR2); |
|||
|
|||
/* was SIGUSR2 handler called? */ |
|||
if (handlerCalled != 0) |
|||
{ |
|||
puts ("FAIL: signal handler was called, but signal was blocked."); |
|||
exit (1); |
|||
} |
|||
|
|||
/* is SIGUSR2 pending? */ |
|||
signalpending (SIGUSR2, "before swapcontext"); |
|||
|
|||
if (swapcontext (&oldctx, &ctx) != 0) |
|||
{ |
|||
printf ("FAIL: swapcontext: %m\n"); |
|||
exit (1); |
|||
} |
|||
|
|||
puts ("after returned from swapcontext"); |
|||
|
|||
if (global != 3) |
|||
{ |
|||
puts ("FAIL: returned from swapcontext without ctx-context called."); |
|||
exit (1); |
|||
} |
|||
|
|||
puts ("test succeeded"); |
|||
return 0; |
|||
} |
|||
else if ( global != 3 ) |
|||
{ |
|||
puts ("FAIL: 'global' not incremented three times"); |
|||
exit (1); |
|||
} |
|||
|
|||
puts ("after swapcontext"); |
|||
/* check SIGUSR1/2 */ |
|||
check ("swapcontext"); |
|||
|
|||
/* was SIGUSR2 handler called? */ |
|||
if (handlerCalled != 1) |
|||
{ |
|||
puts ("FAIL: signal handler was not called after swapcontext."); |
|||
exit (1); |
|||
} |
|||
|
|||
/* check sigmask in old context of swapcontext-call */ |
|||
if (sigismember (&oldctx.uc_sigmask, SIGUSR2) != 1) |
|||
{ |
|||
puts ("FAIL: SIGUSR2 is not blocked in oldctx.uc_sigmask."); |
|||
exit (1); |
|||
} |
|||
|
|||
if (sigismember (&oldctx.uc_sigmask, SIGUSR1) != 1) |
|||
{ |
|||
puts ("FAIL: SIGUSR1 is not blocked in oldctx.uc_sigmaks."); |
|||
exit (1); |
|||
} |
|||
|
|||
/* change to old context, which was gathered by swapcontext() call. */ |
|||
setcontext (&oldctx); |
|||
|
|||
puts ("FAIL: returned from setcontext (&oldctx)"); |
|||
exit (1); |
|||
} |
|||
|
|||
#define TEST_FUNCTION do_test () |
|||
#include "../test-skeleton.c" |
|||
Loading…
Reference in new issue