1 | /* Test that loading libpthread does not break ld.so exceptions (bug 16628). |
2 | Copyright (C) 2016-2022 Free Software Foundation, Inc. |
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 |
17 | <https://www.gnu.org/licenses/>. */ |
18 | |
19 | #include <dlfcn.h> |
20 | #include <signal.h> |
21 | #include <stdio.h> |
22 | #include <string.h> |
23 | #include <sys/wait.h> |
24 | #include <unistd.h> |
25 | |
26 | static int |
27 | do_test (void) |
28 | { |
29 | void *handle = dlopen (file: "tst-latepthreadmod.so" , RTLD_LOCAL | RTLD_LAZY); |
30 | if (handle == NULL) |
31 | { |
32 | printf (format: "error: dlopen failed: %s\n" , dlerror ()); |
33 | return 1; |
34 | } |
35 | void *ptr = dlsym (handle: handle, name: "trigger_dynlink_failure" ); |
36 | if (ptr == NULL) |
37 | { |
38 | printf (format: "error: dlsym failed: %s\n" , dlerror ()); |
39 | return 1; |
40 | } |
41 | int (*func) (void) = ptr; |
42 | |
43 | /* Run the actual test in a subprocess, to capture the error. */ |
44 | int fds[2]; |
45 | if (pipe (pipedes: fds) < 0) |
46 | { |
47 | printf (format: "error: pipe: %m\n" ); |
48 | return 1; |
49 | } |
50 | pid_t pid = fork (); |
51 | if (pid < 0) |
52 | { |
53 | printf (format: "error: fork: %m\n" ); |
54 | return 1; |
55 | } |
56 | else if (pid == 0) |
57 | { |
58 | if (dup2 (fd: fds[1], STDERR_FILENO) < 0) |
59 | _exit (status: 2); |
60 | /* Trigger an abort. */ |
61 | func (); |
62 | _exit (status: 3); |
63 | } |
64 | /* NB: This assumes that the abort message is so short that the pipe |
65 | does not block. */ |
66 | int status; |
67 | if (waitpid (pid: pid, stat_loc: &status, options: 0) < 0) |
68 | { |
69 | printf (format: "error: waitpid: %m\n" ); |
70 | return 1; |
71 | } |
72 | |
73 | /* Check the printed error message. */ |
74 | if (close (fd: fds[1]) < 0) |
75 | { |
76 | printf (format: "error: close: %m\n" ); |
77 | return 1; |
78 | } |
79 | char buf[512]; |
80 | /* Leave room for the NUL terminator. */ |
81 | ssize_t ret = read (fd: fds[0], buf: buf, nbytes: sizeof (buf) - 1); |
82 | if (ret < 0) |
83 | { |
84 | printf (format: "error: read: %m\n" ); |
85 | return 1; |
86 | } |
87 | if (ret > 0 && buf[ret - 1] == '\n') |
88 | --ret; |
89 | buf[ret] = '\0'; |
90 | printf (format: "info: exit status: %d, message: %s\n" , status, buf); |
91 | if (strstr (haystack: buf, needle: "undefined symbol: this_function_is_not_defined" ) == NULL) |
92 | { |
93 | printf (format: "error: message does not contain expected string\n" ); |
94 | return 1; |
95 | } |
96 | if (!WIFEXITED (status) || WEXITSTATUS (status) != 127) |
97 | { |
98 | printf (format: "error: unexpected process exit status\n" ); |
99 | return 1; |
100 | } |
101 | return 0; |
102 | } |
103 | |
104 | #include <support/test-driver.c> |
105 | |