]>
Commit | Line | Data |
---|---|---|
c92d40c0 | 1 | /* Bug 18125: Verify setcontext calls exit() and not _exit(). |
581c785b | 2 | Copyright (C) 2015-2022 Free Software Foundation, Inc. |
c92d40c0 CD |
3 | This file is part of the GNU C Library. |
4 | ||
5 | The GNU C Library is free software; you can redistribute it and/or | |
6 | modify it under the terms of the GNU Lesser General Public | |
7 | License as published by the Free Software Foundation; either | |
8 | version 2.1 of the License, or (at your option) any later version. | |
9 | ||
10 | The GNU C Library is distributed in the hope that it will be useful, | |
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
13 | Lesser General Public License for more details. | |
14 | ||
15 | You should have received a copy of the GNU Lesser General Public | |
16 | License along with the GNU C Library; if not, see | |
5a82c748 | 17 | <https://www.gnu.org/licenses/>. */ |
c92d40c0 CD |
18 | |
19 | #include <errno.h> | |
20 | #include <signal.h> | |
21 | #include <stdio.h> | |
22 | #include <stdlib.h> | |
23 | #include <string.h> | |
24 | #include <ucontext.h> | |
25 | #include <unistd.h> | |
26 | #include <limits.h> | |
27 | #include <sys/types.h> | |
28 | #include <sys/stat.h> | |
29 | #include <fcntl.h> | |
30 | ||
31 | /* Please note that depending on the outcome of Bug 18135 this test | |
32 | may become invalid, and instead of testing for calling exit it | |
33 | should be reworked to test for the last context calling | |
34 | pthread_exit(). */ | |
35 | ||
36 | static ucontext_t ctx; | |
37 | static char *filename; | |
38 | ||
39 | /* It is intended that this function does nothing. */ | |
40 | static void | |
41 | cf (void) | |
42 | { | |
43 | printf ("called context function\n"); | |
44 | } | |
45 | ||
46 | static void | |
47 | exit_called (void) | |
48 | { | |
49 | int fd; | |
50 | ssize_t res; | |
51 | const char buf[] = "Called exit function\n"; | |
52 | ||
53 | fd = open (filename, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR); | |
54 | if (fd == -1) | |
55 | { | |
56 | printf ("FAIL: Unable to create test file %s\n", filename); | |
57 | exit (1); | |
58 | } | |
59 | res = write (fd, buf, sizeof (buf)); | |
60 | if (res != sizeof (buf)) | |
61 | { | |
62 | printf ("FAIL: Expected to write test file in one write call.\n"); | |
63 | exit (1); | |
64 | } | |
65 | res = close (fd); | |
66 | if (res == -1) | |
67 | { | |
68 | printf ("FAIL: Failed to close test file.\n"); | |
69 | exit (1); | |
70 | } | |
71 | printf ("PASS: %s", buf); | |
72 | } | |
73 | ||
74 | /* The test expects a filename given by the wrapper calling script. | |
75 | The test then registers an atexit handler that will create the | |
76 | file to indicate that the atexit handler ran. Then the test | |
77 | creates a context, modifies it with makecontext, and sets it. | |
78 | The context has only a single context which then must exit. | |
79 | If it incorrectly exits via _exit then the atexit handler is | |
80 | not run, the file is not created, and the wrapper detects this | |
81 | and fails the test. This test cannot be done using an _exit | |
82 | interposer since setcontext avoids the PLT and calls _exit | |
83 | directly. */ | |
84 | static int | |
85 | do_test (int argc, char **argv) | |
86 | { | |
87 | int ret; | |
88 | char st1[32768]; | |
89 | ucontext_t tempctx = ctx; | |
90 | ||
91 | if (argc < 2) | |
92 | { | |
93 | printf ("FAIL: Test missing filename argument.\n"); | |
94 | exit (1); | |
95 | } | |
96 | ||
97 | filename = argv[1]; | |
98 | ||
99 | atexit (exit_called); | |
100 | ||
101 | puts ("making contexts"); | |
102 | if (getcontext (&ctx) != 0) | |
103 | { | |
104 | if (errno == ENOSYS) | |
105 | { | |
106 | /* Exit with 77 to mark the test as UNSUPPORTED. */ | |
107 | printf ("UNSUPPORTED: getcontext not implemented.\n"); | |
108 | exit (77); | |
109 | } | |
110 | ||
111 | printf ("FAIL: getcontext failed.\n"); | |
112 | exit (1); | |
113 | } | |
114 | ||
115 | ctx.uc_stack.ss_sp = st1; | |
116 | ctx.uc_stack.ss_size = sizeof (st1); | |
117 | ctx.uc_link = 0; | |
118 | makecontext (&ctx, cf, 0); | |
119 | ||
120 | /* Without this check, a stub makecontext can make us spin forever. */ | |
121 | if (memcmp (&tempctx, &ctx, sizeof ctx) == 0) | |
122 | { | |
123 | puts ("UNSUPPORTED: makecontext was a no-op, presuming not implemented"); | |
124 | exit (77); | |
125 | } | |
126 | ||
127 | ret = setcontext (&ctx); | |
128 | if (ret != 0) | |
129 | { | |
130 | printf ("FAIL: setcontext returned with %d and errno of %d.\n", ret, errno); | |
131 | exit (1); | |
132 | } | |
133 | ||
134 | printf ("FAIL: Impossibly returned to main.\n"); | |
135 | exit (1); | |
136 | } | |
137 | ||
138 | #include "../test-skeleton.c" |