[Sanitizer] add file forgotten in r183730
[blocksruntime.git] / lib / sanitizer_common / sanitizer_symbolizer_posix_libcdep.cc
blobdd6ecbb51c41d66eea885ab6ae9a5bd8438fdedf
1 //===-- sanitizer_symbolizer_posix_libcdep.cc -----------------------------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
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"
16 #if SANITIZER_POSIX
17 #include "sanitizer_common.h"
18 #include "sanitizer_internal_defs.h"
19 #include "sanitizer_symbolizer.h"
21 #include <errno.h>
22 #include <sys/wait.h>
23 #include <unistd.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");
31 return false;
34 int *infd = NULL;
35 int *outfd = NULL;
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).
42 int sock_pair[5][2];
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);
51 return false;
52 } else if (sock_pair[i][0] > 2 && sock_pair[i][1] > 2) {
53 if (infd == NULL) {
54 infd = sock_pair[i];
55 } else {
56 outfd = sock_pair[i];
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]);
62 break;
66 CHECK(infd);
67 CHECK(outfd);
69 int pid = fork();
70 if (pid == -1) {
71 // Fork() failed.
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);
78 return false;
79 } else if (pid == 0) {
80 // Child subprocess.
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--)
90 internal_close(fd);
91 execl(path_to_symbolizer, path_to_symbolizer, (char*)0);
92 internal__exit(1);
95 // Continue execution in parent process.
96 internal_close(outfd[0]);
97 internal_close(infd[1]);
98 *input_fd = infd[0];
99 *output_fd = outfd[1];
101 // Check that symbolizer subprocess started successfully.
102 int pid_status;
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");
108 return false;
111 return true;
115 } // namespace __sanitizer
117 #endif // SANITIZER_POSIX