benchtests: Switch string benchmarks to use bench-timing.h.
[glibc.git] / debug / tst-backtrace5.c
blob51180c1c8c0c7e00bc828c77838a7d5c4f64df1c
1 /* Test backtrace and backtrace_symbols for signal frames, where a
2 system call was interrupted by a signal.
3 Copyright (C) 2011-2013 Free Software Foundation, Inc.
4 This file is part of the GNU C Library.
6 The GNU C Library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2.1 of the License, or (at your option) any later version.
11 The GNU C Library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public
17 License along with the GNU C Library; if not, see
18 <http://www.gnu.org/licenses/>. */
20 #include <execinfo.h>
21 #include <search.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <sys/types.h>
26 #include <signal.h>
27 #include <unistd.h>
29 #include "tst-backtrace.h"
31 #ifndef SIGACTION_FLAGS
32 # define SIGACTION_FLAGS 0
33 #endif
35 static int do_test (void);
36 #define TEST_FUNCTION do_test ()
37 #include "../test-skeleton.c"
39 /* The backtrace should include at least handle_signal, a signal
40 trampoline, read, 3 * fn, and do_test. */
41 #define NUM_FUNCTIONS 7
43 void
44 handle_signal (int signum)
46 void *addresses[NUM_FUNCTIONS];
47 char **symbols;
48 int n;
49 int i;
51 /* Get the backtrace addresses. */
52 n = backtrace (addresses, sizeof (addresses) / sizeof (addresses[0]));
53 printf ("Obtained backtrace with %d functions\n", n);
54 /* Check that there are at least seven functions. */
55 if (n < NUM_FUNCTIONS)
57 FAIL ();
58 return;
60 /* Convert them to symbols. */
61 symbols = backtrace_symbols (addresses, n);
62 /* Check that symbols were obtained. */
63 if (symbols == NULL)
65 FAIL ();
66 return;
68 for (i = 0; i < n; ++i)
69 printf ("Function %d: %s\n", i, symbols[i]);
70 /* Check that the function names obtained are accurate. */
71 if (!match (symbols[0], "handle_signal"))
73 FAIL ();
74 return;
76 /* Do not check name for signal trampoline. */
77 i = 2;
78 if (!match (symbols[i++], "read"))
80 /* Perhaps symbols[2] is __kernel_vsyscall? */
81 if (!match (symbols[i++], "read"))
83 FAIL ();
84 return;
87 for (; i < n - 1; i++)
88 if (!match (symbols[i], "fn"))
90 FAIL ();
91 return;
93 /* Symbol names are not available for static functions, so we do not
94 check do_test. */
97 NO_INLINE int
98 fn (int c, int flags)
100 pid_t parent_pid, child_pid;
101 int pipefd[2];
102 char r[1];
103 struct sigaction act;
105 if (c > 0)
107 fn (c - 1, flags);
108 return x;
111 memset (&act, 0, sizeof (act));
112 act.sa_handler = handle_signal;
113 act.sa_flags = flags;
114 sigemptyset (&act.sa_mask);
115 sigaction (SIGUSR1, &act, NULL);
116 parent_pid = getpid ();
117 if (pipe (pipefd) == -1)
118 abort ();
120 child_pid = fork ();
121 if (child_pid == (pid_t) -1)
122 abort ();
123 else if (child_pid == 0)
125 sleep (1);
126 kill (parent_pid, SIGUSR1);
127 _exit (0);
130 /* In the parent. */
131 read (pipefd[0], r, 1);
133 return 0;
136 NO_INLINE static int
137 do_test (void)
139 fn (2, SIGACTION_FLAGS);
140 return ret;