1 //===-- sanitizer_symbolizer_posix_libcdep.cc -----------------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file is shared between AddressSanitizer and ThreadSanitizer
11 // run-time libraries.
12 // POSIX-specific implementation of symbolizer parts.
13 //===----------------------------------------------------------------------===//
15 #include "sanitizer_platform.h"
17 #include "sanitizer_common.h"
18 #include "sanitizer_internal_defs.h"
19 #include "sanitizer_symbolizer.h"
25 namespace __sanitizer
{
27 bool StartSymbolizerSubprocess(const char *path_to_symbolizer
,
28 int *input_fd
, int *output_fd
) {
29 if (!FileExists(path_to_symbolizer
)) {
30 Report("WARNING: invalid path to external symbolizer!\n");
36 // The client program may close its stdin and/or stdout and/or stderr
37 // thus allowing socketpair to reuse file descriptors 0, 1 or 2.
38 // In this case the communication between the forked processes may be
39 // broken if either the parent or the child tries to close or duplicate
40 // these descriptors. The loop below produces two pairs of file
41 // descriptors, each greater than 2 (stderr).
43 for (int i
= 0; i
< 5; i
++) {
44 if (pipe(sock_pair
[i
]) == -1) {
45 for (int j
= 0; j
< i
; j
++) {
46 internal_close(sock_pair
[j
][0]);
47 internal_close(sock_pair
[j
][1]);
49 Report("WARNING: Can't create a socket pair to start "
50 "external symbolizer (errno: %d)\n", errno
);
52 } else if (sock_pair
[i
][0] > 2 && sock_pair
[i
][1] > 2) {
57 for (int j
= 0; j
< i
; j
++) {
58 if (sock_pair
[j
] == infd
) continue;
59 internal_close(sock_pair
[j
][0]);
60 internal_close(sock_pair
[j
][1]);
72 internal_close(infd
[0]);
73 internal_close(infd
[1]);
74 internal_close(outfd
[0]);
75 internal_close(outfd
[1]);
76 Report("WARNING: failed to fork external symbolizer "
77 " (errno: %d)\n", errno
);
79 } else if (pid
== 0) {
81 internal_close(STDOUT_FILENO
);
82 internal_close(STDIN_FILENO
);
83 internal_dup2(outfd
[0], STDIN_FILENO
);
84 internal_dup2(infd
[1], STDOUT_FILENO
);
85 internal_close(outfd
[0]);
86 internal_close(outfd
[1]);
87 internal_close(infd
[0]);
88 internal_close(infd
[1]);
89 for (int fd
= getdtablesize(); fd
> 2; fd
--)
91 execl(path_to_symbolizer
, path_to_symbolizer
, (char*)0);
95 // Continue execution in parent process.
96 internal_close(outfd
[0]);
97 internal_close(infd
[1]);
99 *output_fd
= outfd
[1];
101 // Check that symbolizer subprocess started successfully.
103 SleepForMillis(kSymbolizerStartupTimeMillis
);
104 int exited_pid
= waitpid(pid
, &pid_status
, WNOHANG
);
105 if (exited_pid
!= 0) {
106 // Either waitpid failed, or child has already exited.
107 Report("WARNING: external symbolizer didn't start up correctly!\n");
115 } // namespace __sanitizer
117 #endif // SANITIZER_POSIX