Skip to content

Commit a0fbdc0

Browse files
committed
[Sanitizer] Option to fallback to stderr if unable to open logfile
1 parent f94e36d commit a0fbdc0

File tree

4 files changed

+37
-8
lines changed

4 files changed

+37
-8
lines changed

compiler-rt/lib/sanitizer_common/sanitizer_file.cpp

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,16 @@ void RawWrite(const char *buffer) {
3636

3737
void ReportFile::ReopenIfNecessary() {
3838
mu->CheckLocked();
39-
if (fd == kStdoutFd || fd == kStderrFd) return;
39+
if (!lastOpenFailed)
40+
if (fd == kStdoutFd || fd == kStderrFd)
41+
return;
4042

4143
uptr pid = internal_getpid();
44+
if (lastOpenFailed && fd_pid != pid) {
45+
fd = kInvalidFd;
46+
lastOpenFailed = false;
47+
}
48+
4249
// If in tracer, use the parent's file.
4350
if (pid == stoptheworld_tracer_pid)
4451
pid = stoptheworld_tracer_ppid;
@@ -48,8 +55,7 @@ void ReportFile::ReopenIfNecessary() {
4855
// process, close it now.
4956
if (fd_pid == pid)
5057
return;
51-
else
52-
CloseFile(fd);
58+
CloseFile(fd);
5359
}
5460

5561
const char *exe_name = GetProcessName();
@@ -71,12 +77,17 @@ void ReportFile::ReopenIfNecessary() {
7177
char errmsg[100];
7278
internal_snprintf(errmsg, sizeof(errmsg), " (reason: %d)\n", err);
7379
WriteToFile(kStderrFd, errmsg, internal_strlen(errmsg));
74-
Die();
80+
if (!common_flags()->log_fallback_to_stderr)
81+
Die();
82+
const char *errmsg2 = "ERROR: Fallback to stderr\n";
83+
WriteToFile(kStderrFd, errmsg2, internal_strlen(errmsg2));
84+
lastOpenFailed = true;
85+
fd = kStderrFd;
7586
}
7687
fd_pid = pid;
7788
}
7889

79-
static void RecursiveCreateParentDirs(char *path) {
90+
static void RecursiveCreateParentDirs(char *path, fd_t &fd) {
8091
if (path[0] == '\0')
8192
return;
8293
for (int i = 1; path[i] != '\0'; ++i) {
@@ -90,7 +101,13 @@ static void RecursiveCreateParentDirs(char *path) {
90101
WriteToFile(kStderrFd, path, internal_strlen(path));
91102
const char *ErrorMsgSuffix = "\n";
92103
WriteToFile(kStderrFd, ErrorMsgSuffix, internal_strlen(ErrorMsgSuffix));
93-
Die();
104+
if (!common_flags()->log_fallback_to_stderr)
105+
Die();
106+
path[i] = save;
107+
const char *ErrorMsgSuffix2 = "ERROR: Fallback to stderr\n";
108+
WriteToFile(kStderrFd, ErrorMsgSuffix2, internal_strlen(ErrorMsgSuffix2));
109+
fd = kStderrFd;
110+
return;
94111
}
95112
path[i] = save;
96113
}
@@ -166,7 +183,11 @@ void ReportFile::SetReportPath(const char *path) {
166183
WriteToFile(kStderrFd, path, 8);
167184
message = "...\n";
168185
WriteToFile(kStderrFd, message, internal_strlen(message));
169-
Die();
186+
if (!common_flags()->log_fallback_to_stderr)
187+
Die();
188+
const char *message2 = "ERROR: Fallback to stderr\n";
189+
WriteToFile(kStderrFd, message2, internal_strlen(message2));
190+
path = "stderr";
170191
}
171192
}
172193

@@ -180,7 +201,7 @@ void ReportFile::SetReportPath(const char *path) {
180201
fd = kStdoutFd;
181202
} else {
182203
ParseAndSetPath(path, path_prefix, kMaxPathLength);
183-
RecursiveCreateParentDirs(path_prefix);
204+
RecursiveCreateParentDirs(path_prefix, fd);
184205
}
185206
}
186207

compiler-rt/lib/sanitizer_common/sanitizer_file.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,9 @@ struct ReportFile {
4343
// PID of the process that opened fd. If a fork() occurs,
4444
// the PID of child will be different from fd_pid.
4545
uptr fd_pid;
46+
// Set to true if the last attempt to open the logfile failed, perhaps due to
47+
// permission errors
48+
bool lastOpenFailed = false;
4649

4750
private:
4851
void ReopenIfNecessary();

compiler-rt/lib/sanitizer_common/sanitizer_flags.inc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,8 @@ COMMON_FLAG(
6565
bool, log_to_syslog, (bool)SANITIZER_ANDROID || (bool)SANITIZER_APPLE,
6666
"Write all sanitizer output to syslog in addition to other means of "
6767
"logging.")
68+
COMMON_FLAG(bool, log_fallback_to_stderr, false,
69+
"When set, fallback to stderr if we are unable to open log path.")
6870
COMMON_FLAG(
6971
int, verbosity, 0,
7072
"Verbosity level (0 - silent, 1 - a bit of output, 2+ - more output).")

compiler-rt/test/sanitizer_common/TestCases/Posix/sanitizer_set_report_path_fail.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,11 @@
22

33
// Case 1: Try setting a path that is an invalid/inaccessible directory.
44
// RUN: not %run %t 2>&1 | FileCheck %s --check-prefix=ERROR1
5+
// RUN: %env_tool_opts=log_fallback_to_stderr=1 %run %t 2>&1 | FileCheck %s --check-prefixes=ERROR1,FALLBACK
56

67
// Case 2: Try setting a path that is too large.
78
// RUN: not %run %t A 2>&1 | FileCheck %s --check-prefix=ERROR2
9+
// RUN: %env_tool_opts=log_fallback_to_stderr=1 %run %t A 2>&1 | FileCheck %s --check-prefixes=ERROR2,FALLBACK
810

911
#include <sanitizer/common_interface_defs.h>
1012
#include <stdio.h>
@@ -22,3 +24,4 @@ int main(int argc, char **argv) {
2224
}
2325
__sanitizer_set_report_path(buff);
2426
}
27+
// FALLBACK: Fallback to stderr

0 commit comments

Comments
 (0)