summaryrefslogtreecommitdiff
path: root/stdlib
diff options
context:
space:
mode:
Diffstat (limited to 'stdlib')
-rw-r--r--stdlib/Makefile9
-rw-r--r--stdlib/tst-setcontext3.c138
-rw-r--r--stdlib/tst-setcontext3.sh54
3 files changed, 200 insertions, 1 deletions
diff --git a/stdlib/Makefile b/stdlib/Makefile
index c78fdb51ec..3300dd2142 100644
--- a/stdlib/Makefile
+++ b/stdlib/Makefile
@@ -73,7 +73,8 @@ tests := tst-strtol tst-strtod testmb testrand testsort testdiv \
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
+ tst-tininess tst-strtod-underflow tst-tls-atexit \
+ tst-setcontext3
tests-static := tst-secure-getenv
modules-names = tst-tls-atexit-lib
@@ -157,3 +158,9 @@ tst-tls-atexit-lib.so-no-z-defs = yes
$(objpfx)tst-tls-atexit: $(shared-thread-library) $(libdl)
$(objpfx)tst-tls-atexit.out: $(objpfx)tst-tls-atexit-lib.so
+
+$(objpfx)tst-setcontext3.out: tst-setcontext3.sh $(objpfx)tst-setcontext3
+ $(SHELL) $< $(common-objpfx) '$(test-program-prefix-before-env)' \
+ '$(run-program-env)' '$(test-program-prefix-after-env)' \
+ $(common-objpfx)stdlib/; \
+ $(evaluate-test)
diff --git a/stdlib/tst-setcontext3.c b/stdlib/tst-setcontext3.c
new file mode 100644
index 0000000000..fda21285c6
--- /dev/null
+++ b/stdlib/tst-setcontext3.c
@@ -0,0 +1,138 @@
+/* Bug 18125: Verify setcontext calls exit() and not _exit().
+ 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 <errno.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ucontext.h>
+#include <unistd.h>
+#include <limits.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+/* Please note that depending on the outcome of Bug 18135 this test
+ may become invalid, and instead of testing for calling exit it
+ should be reworked to test for the last context calling
+ pthread_exit(). */
+
+static ucontext_t ctx;
+static char *filename;
+
+/* It is intended that this function does nothing. */
+static void
+cf (void)
+{
+ printf ("called context function\n");
+}
+
+static void
+exit_called (void)
+{
+ int fd;
+ ssize_t res;
+ const char buf[] = "Called exit function\n";
+
+ fd = open (filename, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR);
+ if (fd == -1)
+ {
+ printf ("FAIL: Unable to create test file %s\n", filename);
+ exit (1);
+ }
+ res = write (fd, buf, sizeof (buf));
+ if (res != sizeof (buf))
+ {
+ printf ("FAIL: Expected to write test file in one write call.\n");
+ exit (1);
+ }
+ res = close (fd);
+ if (res == -1)
+ {
+ printf ("FAIL: Failed to close test file.\n");
+ exit (1);
+ }
+ printf ("PASS: %s", buf);
+}
+
+/* The test expects a filename given by the wrapper calling script.
+ The test then registers an atexit handler that will create the
+ file to indicate that the atexit handler ran. Then the test
+ creates a context, modifies it with makecontext, and sets it.
+ The context has only a single context which then must exit.
+ If it incorrectly exits via _exit then the atexit handler is
+ not run, the file is not created, and the wrapper detects this
+ and fails the test. This test cannot be done using an _exit
+ interposer since setcontext avoids the PLT and calls _exit
+ directly. */
+static int
+do_test (int argc, char **argv)
+{
+ int ret;
+ char st1[32768];
+ ucontext_t tempctx = ctx;
+
+ if (argc < 2)
+ {
+ printf ("FAIL: Test missing filename argument.\n");
+ exit (1);
+ }
+
+ filename = argv[1];
+
+ atexit (exit_called);
+
+ puts ("making contexts");
+ if (getcontext (&ctx) != 0)
+ {
+ if (errno == ENOSYS)
+ {
+ /* Exit with 77 to mark the test as UNSUPPORTED. */
+ printf ("UNSUPPORTED: getcontext not implemented.\n");
+ exit (77);
+ }
+
+ printf ("FAIL: getcontext failed.\n");
+ exit (1);
+ }
+
+ ctx.uc_stack.ss_sp = st1;
+ ctx.uc_stack.ss_size = sizeof (st1);
+ ctx.uc_link = 0;
+ makecontext (&ctx, cf, 0);
+
+ /* Without this check, a stub makecontext can make us spin forever. */
+ if (memcmp (&tempctx, &ctx, sizeof ctx) == 0)
+ {
+ puts ("UNSUPPORTED: makecontext was a no-op, presuming not implemented");
+ exit (77);
+ }
+
+ ret = setcontext (&ctx);
+ if (ret != 0)
+ {
+ printf ("FAIL: setcontext returned with %d and errno of %d.\n", ret, errno);
+ exit (1);
+ }
+
+ printf ("FAIL: Impossibly returned to main.\n");
+ exit (1);
+}
+
+#include "../test-skeleton.c"
diff --git a/stdlib/tst-setcontext3.sh b/stdlib/tst-setcontext3.sh
new file mode 100644
index 0000000000..6ad67a8aeb
--- /dev/null
+++ b/stdlib/tst-setcontext3.sh
@@ -0,0 +1,54 @@
+#! /bin/bash
+# Bug 18125: Test the exit functionality of setcontext().
+# 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/>.
+
+set -e
+
+common_objpfx=$1
+test_program_prefix_before_env=$2
+run_program_env=$3
+test_program_prefix_after_env=$4
+objpfx=$5
+
+test_pre="${test_program_prefix_before_env} ${run_program_env}"
+test="${test_program_prefix_after_env} ${objpfx}tst-setcontext3"
+out=${objpfx}tst-setcontext3.out
+
+tempfiles=()
+cleanup() {
+ rm -f "${tempfiles[@]}"
+}
+trap cleanup 0
+
+tempfile=$(mktemp "tst-setcontext3.XXXXXXXXXX")
+tempfiles+=("$tempfile")
+
+# We want to run the test program and see if secontext called
+# exit() and wrote out the test file we specified. If the
+# test exits with a non-zero status this will fail because we
+# are using `set -e`.
+$test_pre $test "$tempfile"
+
+# Look for resulting file.
+if [ -e "$tempfile" ]; then
+ echo "PASS: tst-setcontext3 an exit() and created $tempfile"
+ exit 0
+else
+ echo "FAIL: tst-setcontext3 did not create $tempfile"
+ exit 1
+fi