1 /* Test that loading libpthread does not break ld.so exceptions (bug 16628).
2    Copyright (C) 2016-2021 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
do_test(void)27 do_test (void)
28 {
29   void *handle = dlopen ("tst-latepthreadmod.so", RTLD_LOCAL | RTLD_LAZY);
30   if (handle == NULL)
31     {
32       printf ("error: dlopen failed: %s\n", dlerror ());
33       return 1;
34     }
35   void *ptr = dlsym (handle, "trigger_dynlink_failure");
36   if (ptr == NULL)
37     {
38       printf ("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 (fds) < 0)
46     {
47       printf ("error: pipe: %m\n");
48       return 1;
49     }
50   pid_t pid = fork ();
51   if (pid < 0)
52     {
53       printf ("error: fork: %m\n");
54       return 1;
55     }
56   else if (pid == 0)
57     {
58       if (dup2 (fds[1], STDERR_FILENO) < 0)
59         _exit (2);
60       /* Trigger an abort.  */
61       func ();
62       _exit (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, &status, 0) < 0)
68     {
69       printf ("error: waitpid: %m\n");
70       return 1;
71     }
72 
73   /* Check the printed error message.  */
74   if (close (fds[1]) < 0)
75    {
76      printf ("error: close: %m\n");
77      return 1;
78    }
79   char buf[512];
80   /* Leave room for the NUL terminator.  */
81   ssize_t ret = read (fds[0], buf, sizeof (buf) - 1);
82   if (ret < 0)
83     {
84       printf ("error: read: %m\n");
85       return 1;
86     }
87   if (ret > 0 && buf[ret - 1] == '\n')
88     --ret;
89   buf[ret] = '\0';
90   printf ("info: exit status: %d, message: %s\n", status, buf);
91   if (strstr (buf, "undefined symbol: this_function_is_not_defined") == NULL)
92     {
93       printf ("error: message does not contain expected string\n");
94       return 1;
95     }
96   if (!WIFEXITED (status) || WEXITSTATUS (status) != 127)
97     {
98       printf ("error: unexpected process exit status\n");
99       return 1;
100     }
101   return 0;
102 }
103 
104 #include <support/test-driver.c>
105