summaryrefslogtreecommitdiff
path: root/lib/sanitizer_common/sanitizer_common.cc
diff options
context:
space:
mode:
authorAlexey Samsonov <vonosmas@gmail.com>2014-12-11 18:30:25 +0000
committerAlexey Samsonov <vonosmas@gmail.com>2014-12-11 18:30:25 +0000
commitbeb92e063e965d35b7dd513fb69e766b609bd884 (patch)
treeab078812ccd24a3e14fb856ed81fd61282e0988b /lib/sanitizer_common/sanitizer_common.cc
parent289734dae9b04790f6ccf9c14575bc2e0e27d725 (diff)
[Sanitizer] Fix report_path functionality:
Summary: - Make sure mmap() is never called inside RawWrite function. - Wrap a bunch of standalone globals in a ReportFile object. - Make sure accesses to these globals are thread-safe. - Fix report_path functionality on Windows, where __sanitizer_set_report_path() would break program. I've started this yak shaving in order to make "CommonFlags::mmap_limit_mb" immutable. Currently we drop this flag to zero before printing an error message. Test Plan: regression test suite Reviewers: kcc, glider Subscribers: llvm-commits Differential Revision: http://reviews.llvm.org/D6595 git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@224031 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/sanitizer_common/sanitizer_common.cc')
-rw-r--r--lib/sanitizer_common/sanitizer_common.cc92
1 files changed, 58 insertions, 34 deletions
diff --git a/lib/sanitizer_common/sanitizer_common.cc b/lib/sanitizer_common/sanitizer_common.cc
index 737177c9d..eb5ed363c 100644
--- a/lib/sanitizer_common/sanitizer_common.cc
+++ b/lib/sanitizer_common/sanitizer_common.cc
@@ -26,19 +26,66 @@ uptr GetPageSizeCached() {
return PageSize;
}
+StaticSpinMutex report_file_mu;
+ReportFile report_file = {&report_file_mu, kStderrFd, "", "", 0};
-// By default, dump to stderr. If |log_to_file| is true and |report_fd_pid|
-// isn't equal to the current PID, try to obtain file descriptor by opening
-// file "report_path_prefix.<PID>".
-fd_t report_fd = kStderrFd;
+void RawWrite(const char *buffer) {
+ report_file.Write(buffer, internal_strlen(buffer));
+}
-// Set via __sanitizer_set_report_path.
-bool log_to_file = false;
-char report_path_prefix[sizeof(report_path_prefix)];
+void ReportFile::ReopenIfNecessary() {
+ mu->CheckLocked();
+ if (fd == kStdoutFd || fd == kStderrFd) return;
+
+ uptr pid = internal_getpid();
+ // If in tracer, use the parent's file.
+ if (pid == stoptheworld_tracer_pid)
+ pid = stoptheworld_tracer_ppid;
+ if (fd != kInvalidFd) {
+ // If the report file is already opened by the current process,
+ // do nothing. Otherwise the report file was opened by the parent
+ // process, close it now.
+ if (fd_pid == pid)
+ return;
+ else
+ internal_close(fd);
+ }
-// PID of process that opened |report_fd|. If a fork() occurs, the PID of the
-// child thread will be different from |report_fd_pid|.
-uptr report_fd_pid = 0;
+ internal_snprintf(full_path, kMaxPathLength, "%s.%zu", path_prefix, pid);
+ uptr openrv = OpenFile(full_path, true);
+ if (internal_iserror(openrv)) {
+ const char *ErrorMsgPrefix = "ERROR: Can't open file: ";
+ internal_write(kStderrFd, ErrorMsgPrefix, internal_strlen(ErrorMsgPrefix));
+ internal_write(kStderrFd, full_path, internal_strlen(full_path));
+ Die();
+ }
+ fd = openrv;
+ fd_pid = pid;
+}
+
+void ReportFile::SetReportPath(const char *path) {
+ if (!path)
+ return;
+ uptr len = internal_strlen(path);
+ if (len > sizeof(path_prefix) - 100) {
+ Report("ERROR: Path is too long: %c%c%c%c%c%c%c%c...\n",
+ path[0], path[1], path[2], path[3],
+ path[4], path[5], path[6], path[7]);
+ Die();
+ }
+
+ SpinMutexLock l(mu);
+ if (fd != kStdoutFd && fd != kStderrFd && fd != kInvalidFd)
+ internal_close(fd);
+ fd = kInvalidFd;
+ if (internal_strcmp(path, "stdout") == 0) {
+ fd = kStdoutFd;
+ } else if (internal_strcmp(path, "stderr") == 0) {
+ fd = kStderrFd;
+ } else {
+ internal_snprintf(path_prefix, kMaxPathLength, "%s", path);
+ }
+}
// PID of the tracer task in StopTheWorld. It shares the address space with the
// main process, but has a different PID and thus requires special handling.
@@ -230,30 +277,7 @@ using namespace __sanitizer; // NOLINT
extern "C" {
void __sanitizer_set_report_path(const char *path) {
- if (!path)
- return;
- uptr len = internal_strlen(path);
- if (len > sizeof(report_path_prefix) - 100) {
- Report("ERROR: Path is too long: %c%c%c%c%c%c%c%c...\n",
- path[0], path[1], path[2], path[3],
- path[4], path[5], path[6], path[7]);
- Die();
- }
- if (report_fd != kStdoutFd &&
- report_fd != kStderrFd &&
- report_fd != kInvalidFd)
- internal_close(report_fd);
- report_fd = kInvalidFd;
- log_to_file = false;
- if (internal_strcmp(path, "stdout") == 0) {
- report_fd = kStdoutFd;
- } else if (internal_strcmp(path, "stderr") == 0) {
- report_fd = kStderrFd;
- } else {
- internal_strncpy(report_path_prefix, path, sizeof(report_path_prefix));
- report_path_prefix[len] = '\0';
- log_to_file = true;
- }
+ report_file.SetReportPath(path);
}
void __sanitizer_report_error_summary(const char *error_summary) {