forked from OSchip/llvm-project
sanitizers: Make sure Visual Studio gets error reports
Visual Studio appears to close stderr before launching a non-console win32 program. This means we don't see any sanitizer reports. If stderr printing fails, call OutputDebugStringA to get the reports into the Visual Studio debugger console. llvm-svn: 190030
This commit is contained in:
parent
2f58696ddd
commit
d483c072af
|
@ -26,16 +26,19 @@ uptr GetPageSizeCached() {
|
|||
return PageSize;
|
||||
}
|
||||
|
||||
static bool log_to_file = false; // Set to true by __sanitizer_set_report_path
|
||||
|
||||
// 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;
|
||||
static char report_path_prefix[4096]; // Set via __sanitizer_set_report_path.
|
||||
|
||||
// Set via __sanitizer_set_report_path.
|
||||
bool log_to_file = false;
|
||||
char report_path_prefix[sizeof(report_path_prefix)];
|
||||
|
||||
// PID of process that opened |report_fd|. If a fork() occurs, the PID of the
|
||||
// child thread will be different from |report_fd_pid|.
|
||||
static uptr report_fd_pid = 0;
|
||||
uptr report_fd_pid = 0;
|
||||
|
||||
static DieCallbackType DieCallback;
|
||||
void SetDieCallback(DieCallbackType callback) {
|
||||
|
@ -68,36 +71,6 @@ void NORETURN CheckFailed(const char *file, int line, const char *cond,
|
|||
Die();
|
||||
}
|
||||
|
||||
void MaybeOpenReportFile() {
|
||||
if (!log_to_file || (report_fd_pid == internal_getpid())) return;
|
||||
InternalScopedBuffer<char> report_path_full(4096);
|
||||
internal_snprintf(report_path_full.data(), report_path_full.size(),
|
||||
"%s.%d", report_path_prefix, internal_getpid());
|
||||
uptr openrv = OpenFile(report_path_full.data(), true);
|
||||
if (internal_iserror(openrv)) {
|
||||
report_fd = kStderrFd;
|
||||
log_to_file = false;
|
||||
Report("ERROR: Can't open file: %s\n", report_path_full.data());
|
||||
Die();
|
||||
}
|
||||
if (report_fd != kInvalidFd) {
|
||||
// We're in the child. Close the parent's log.
|
||||
internal_close(report_fd);
|
||||
}
|
||||
report_fd = openrv;
|
||||
report_fd_pid = internal_getpid();
|
||||
}
|
||||
|
||||
void RawWrite(const char *buffer) {
|
||||
static const char *kRawWriteError = "RawWrite can't output requested buffer!";
|
||||
uptr length = (uptr)internal_strlen(buffer);
|
||||
MaybeOpenReportFile();
|
||||
if (length != internal_write(report_fd, buffer, length)) {
|
||||
internal_write(report_fd, kRawWriteError, internal_strlen(kRawWriteError));
|
||||
Die();
|
||||
}
|
||||
}
|
||||
|
||||
uptr ReadFileToBuffer(const char *file_name, char **buff,
|
||||
uptr *buff_size, uptr max_len) {
|
||||
uptr PageSize = GetPageSizeCached();
|
||||
|
|
|
@ -116,6 +116,9 @@ void SetPrintfAndReportCallback(void (*callback)(const char *));
|
|||
extern StaticSpinMutex CommonSanitizerReportMutex;
|
||||
void MaybeOpenReportFile();
|
||||
extern fd_t report_fd;
|
||||
extern bool log_to_file;
|
||||
extern char report_path_prefix[4096];
|
||||
extern uptr report_fd_pid;
|
||||
|
||||
uptr OpenFile(const char *filename, bool write);
|
||||
// Opens the file 'file_name" and reads up to 'max_len' bytes.
|
||||
|
|
|
@ -197,6 +197,37 @@ char *FindPathToBinary(const char *name) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
void MaybeOpenReportFile() {
|
||||
if (!log_to_file || (report_fd_pid == internal_getpid())) return;
|
||||
InternalScopedBuffer<char> report_path_full(4096);
|
||||
internal_snprintf(report_path_full.data(), report_path_full.size(),
|
||||
"%s.%d", report_path_prefix, internal_getpid());
|
||||
uptr openrv = OpenFile(report_path_full.data(), true);
|
||||
if (internal_iserror(openrv)) {
|
||||
report_fd = kStderrFd;
|
||||
log_to_file = false;
|
||||
Report("ERROR: Can't open file: %s\n", report_path_full.data());
|
||||
Die();
|
||||
}
|
||||
if (report_fd != kInvalidFd) {
|
||||
// We're in the child. Close the parent's log.
|
||||
internal_close(report_fd);
|
||||
}
|
||||
report_fd = openrv;
|
||||
report_fd_pid = internal_getpid();
|
||||
}
|
||||
|
||||
void RawWrite(const char *buffer) {
|
||||
static const char *kRawWriteError =
|
||||
"RawWrite can't output requested buffer!\n";
|
||||
uptr length = (uptr)internal_strlen(buffer);
|
||||
MaybeOpenReportFile();
|
||||
if (length != internal_write(report_fd, buffer, length)) {
|
||||
internal_write(report_fd, kRawWriteError, internal_strlen(kRawWriteError));
|
||||
Die();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace __sanitizer
|
||||
|
||||
#endif // SANITIZER_LINUX || SANITIZER_MAC
|
||||
|
|
|
@ -398,6 +398,24 @@ void GetStackTrace(StackTrace *stack, uptr max_s, uptr pc, uptr bp,
|
|||
stack->trace[i] = (uptr)tmp[i + offset];
|
||||
}
|
||||
|
||||
void MaybeOpenReportFile() {
|
||||
// Windows doesn't have native fork, and we don't support Cygwin or other
|
||||
// environments that try to fake it, so the initial report_fd will always be
|
||||
// correct.
|
||||
}
|
||||
|
||||
void RawWrite(const char *buffer) {
|
||||
static const char *kRawWriteError =
|
||||
"RawWrite can't output requested buffer!\n";
|
||||
uptr length = (uptr)internal_strlen(buffer);
|
||||
if (length != internal_write(report_fd, buffer, length)) {
|
||||
// stderr may be closed, but we may be able to print to the debugger
|
||||
// instead. This is the case when launching a program from Visual Studio,
|
||||
// and the following routine should write to its console.
|
||||
OutputDebugStringA(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace __sanitizer
|
||||
|
||||
#endif // _WIN32
|
||||
|
|
Loading…
Reference in New Issue