]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
S/390: Fix setcontext/swapcontext which are not restoring sigmask.
authorStefan Liebler <stli@linux.vnet.ibm.com>
Thu, 12 Mar 2015 10:08:11 +0000 (11:08 +0100)
committerAndreas Krebbel <krebbel@linux.vnet.ibm.com>
Thu, 12 Mar 2015 10:08:11 +0000 (11:08 +0100)
ChangeLog
NEWS
stdlib/Makefile
stdlib/tst-setcontext2.c [new file with mode: 0644]
sysdeps/unix/sysv/linux/s390/s390-32/setcontext.S
sysdeps/unix/sysv/linux/s390/s390-32/swapcontext.S
sysdeps/unix/sysv/linux/s390/s390-64/setcontext.S
sysdeps/unix/sysv/linux/s390/s390-64/swapcontext.S

index 19d59d8cb03692096ca30291d471c03489732c5a..21725f457321bdff518fdda52665f86c689becc6 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,19 @@
+2015-03-12  Stefan Liebler  <stli@linux.vnet.ibm.com>
+
+       [BZ #18080]
+       * sysdeps/unix/sysv/linux/s390/s390-32/setcontext.S
+       (__setcontext): Use SIG_SETMASK instead of SIG_BLOCK.
+       * sysdeps/unix/sysv/linux/s390/s390-64/setcontext.S
+       (__setcontext): Likewise.
+       * sysdeps/unix/sysv/linux/s390/s390-32/swapcontext.S
+       (__swapcontext): Use SIG_SETMASK instead of SIG_BLOCK.
+       Call rt_sigprocmask syscall one time to set new signal mask
+       and retrieve the current signal mask instead of two calls.
+       * sysdeps/unix/sysv/linux/s390/s390-64/swapcontext.S
+       (__swapcontext): Likewise.
+       * stdlib/Makefile (tests): Add new testcase tst-setcontext2.
+       * stdlib/tst-setcontext2.c: New file.
+
 2015-03-12  Stefan Liebler  <stli@linux.vnet.ibm.com>
 
        * sysdeps/s390/fpu/libm-test-ulps: Regenerate.
diff --git a/NEWS b/NEWS
index 65680853332a43ea9c7dcec2422e3c6268b635ff..88bfc44a3361c4d27f1e839e4f339f4c3e103eee 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -14,7 +14,7 @@ Version 2.22
   17792, 17836, 17912, 17916, 17932, 17944, 17949, 17964, 17965, 17967,
   17969, 17978, 17987, 17991, 17996, 17998, 17999, 18019, 18020, 18029,
   18030, 18032, 18036, 18038, 18039, 18042, 18043, 18046, 18047, 18068,
-  18093, 18104, 18110, 18111.
+  18080, 18093, 18104, 18110, 18111.
 
 * Character encoding and ctype tables were updated to Unicode 7.0.0, using
   new generator scripts contributed by Pravin Satpute and Mike FABIAN (Red
index 92ceca708a2158da760dcc91c45de0769af9f0f5..c78fdb51ecc6567dc06c31059afca29da9e3d172 100644 (file)
@@ -66,11 +66,11 @@ test-srcs   := tst-fmtmsg
 tests          := tst-strtol tst-strtod testmb testrand testsort testdiv   \
                   test-canon test-canon2 tst-strtoll tst-environ           \
                   tst-xpg-basename tst-random tst-random2 tst-bsearch      \
-                  tst-limits tst-rand48 bug-strtod tst-setcontext          \
-                  test-a64l tst-qsort tst-system testmb2 bug-strtod2       \
-                  tst-atof1 tst-atof2 tst-strtod2 tst-strtod3 tst-rand48-2 \
-                  tst-makecontext tst-strtod4 tst-strtod5 tst-qsort2       \
-                  tst-makecontext2 tst-strtod6 tst-unsetenv1               \
+                  tst-limits tst-rand48 bug-strtod tst-setcontext          \
+                  tst-setcontext2 test-a64l tst-qsort tst-system testmb2   \
+                  bug-strtod2 tst-atof1 tst-atof2 tst-strtod2 tst-strtod3  \
+                  tst-rand48-2 tst-makecontext tst-strtod4 tst-strtod5     \
+                  tst-qsort2 tst-makecontext2 tst-strtod6 tst-unsetenv1    \
                   tst-makecontext3 bug-getcontext bug-fmtmsg1              \
                   tst-secure-getenv tst-strtod-overflow tst-strtod-round   \
                   tst-tininess tst-strtod-underflow tst-tls-atexit
diff --git a/stdlib/tst-setcontext2.c b/stdlib/tst-setcontext2.c
new file mode 100644 (file)
index 0000000..8582cc0
--- /dev/null
@@ -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"
index 22fb3ae8e5b87789e461dcdbd6e937f65ad34d01..59cf4a86e80f2cabbe2c27f56b3e00e3cb8a587a 100644 (file)
@@ -34,7 +34,7 @@ ENTRY(__setcontext)
        lr      %r1,%r2
 
        /* rt_sigprocmask (SIG_SETMASK, &sc->sc_mask, NULL, sigsetsize).  */
-       la      %r2,SIG_BLOCK
+       la      %r2,SIG_SETMASK
        la      %r3,SC_MASK(%r1)
        slr     %r4,%r4
        lhi     %r5,_NSIG8
index c40f46589919269adc58163938aee4be96bb3ec0..ac6568b0f3a74171f8d8aec9bceed306ea1586de 100644 (file)
@@ -24,7 +24,7 @@
 /*  __swapcontext (ucontext_t *oucp, const ucontext_t *ucp)
 
   Saves the machine context in oucp such that when it is activated,
-  it appears as if __swapcontextt() returned again, restores the
+  it appears as if __swapcontext() returned again, restores the
   machine context in ucp and thereby resumes execution in that
   context.
 
@@ -39,13 +39,6 @@ ENTRY(__swapcontext)
        lr      %r1,%r2
        lr      %r0,%r3
 
-       /* sigprocmask (SIG_BLOCK, NULL, &sc->sc_mask).  */
-       la      %r2,SIG_BLOCK
-       slr     %r3,%r3
-       la      %r4,SC_MASK(%r1)
-       lhi     %r5,_NSIG8
-       svc     SYS_ify(rt_sigprocmask)
-
        /* Store fpu context.  */
        stfpc   SC_FPC(%r1)
        std     %f0,SC_FPRS(%r1)
@@ -74,11 +67,12 @@ ENTRY(__swapcontext)
        /* Store general purpose registers.  */
        stm     %r0,%r15,SC_GPRS(%r1)
 
-       /* sigprocmask (SIG_SETMASK, &sc->sc_mask, NULL).  */
-       la      %r2,SIG_BLOCK
+       /* rt_sigprocmask (SIG_SETMASK, &ucp->uc_sigmask, &oucp->uc_sigmask,
+          sigsetsize).  */
+       la      %r2,SIG_SETMASK
        lr      %r5,%r0
        la      %r3,SC_MASK(%r5)
-       slr     %r4,%r4
+       la      %r4,SC_MASK(%r1)
        lhi     %r5,_NSIG8
        svc     SYS_ify(rt_sigprocmask)
 
index d83fa42f2c0d971bcf11f60105e181746c4d4b10..388c7d66952dff902700e4e3ee7d2efce9709ba0 100644 (file)
@@ -34,7 +34,7 @@ ENTRY(__setcontext)
        lgr     %r1,%r2
 
        /* sigprocmask (SIG_SETMASK, &sc->sc_mask, NULL).  */
-       la      %r2,SIG_BLOCK
+       la      %r2,SIG_SETMASK
        la      %r3,SC_MASK(%r1)
        slgr    %r4,%r4
        lghi    %r5,_NSIG8
index d36a62366dddb8388e87b26c1bf18461ebb1d1d9..e0336dac1d89c3f626790657f0c7f40c281cbefb 100644 (file)
@@ -24,7 +24,7 @@
 /*  __swapcontext (ucontext_t *oucp, const ucontext_t *ucp)
 
   Saves the machine context in oucp such that when it is activated,
-  it appears as if __swapcontextt() returned again, restores the
+  it appears as if __swapcontext() returned again, restores the
   machine context in ucp and thereby resumes execution in that
   context.
 
@@ -39,13 +39,6 @@ ENTRY(__swapcontext)
        lgr     %r1,%r2
        lgr     %r0,%r3
 
-       /* sigprocmask (SIG_BLOCK, NULL, &sc->sc_mask).  */
-       la      %r2,SIG_BLOCK
-       slgr    %r3,%r3
-       la      %r4,SC_MASK(%r1)
-       lghi    %r5,_NSIG8
-       svc     SYS_ify(rt_sigprocmask)
-
        /* Store fpu context.  */
        stfpc   SC_FPC(%r1)
        std     %f0,SC_FPRS(%r1)
@@ -74,12 +67,13 @@ ENTRY(__swapcontext)
        /* Store general purpose registers.  */
        stmg    %r0,%r15,SC_GPRS(%r1)
 
-       /* rt_sigprocmask (SIG_SETMASK, &sc->sc_mask, NULL, sigsetsize).  */
-       la      %r2,SIG_BLOCK
+       /* rt_sigprocmask (SIG_SETMASK, &ucp->uc_sigmask, &oucp->uc_sigmask,
+          sigsetsize).  */
+       la      %r2,SIG_SETMASK
        lgr     %r5,%r0
        la      %r3,SC_MASK(%r5)
+       la      %r4,SC_MASK(%r1)
        lghi    %r5,_NSIG8
-       slgr    %r4,%r4
        svc     SYS_ify(rt_sigprocmask)
 
        /* Load fpu context.  */