Skip to content

Commit 0605ef7

Browse files
committed
[LLVM][Windows] Elide PrettyStackTrace output for usage errors
On Windows, LLVM’s `reportFatalUsageError` (#138251) may emit a bug report prompt due to the `PrettyStackTrace` signal handler, initialized via `InitLLVM`. This occurs when `RunInterruptHandlers()` is called from `reportFatalUsageError`. This behavior is misleading for usage errors. For example, one of Sony’s customers filed a bug after specifying an invalid LTO cache directory - a clear usage error - because the toolchain output included instructions to report a bug. This patch suppresses `PrettyStackTrace` output for usage errors by adding a flag to `sys::RunInterruptHandlers()` to indicate whether signal handlers should be executed. To test this, I have modified the invalid LTO pipeline errors to call `reportFatalUsageError`, and I have updated the existing LLD test to additionally verify that no bug report message has been emitted. LLVM Issue: #140953 Internal Tracker: TOOLCHAIN-17744
1 parent c21416d commit 0605ef7

File tree

12 files changed

+31
-21
lines changed

12 files changed

+31
-21
lines changed

clang/tools/clang-repl/ClangRepl.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ static void LLVMErrorHandler(void *UserData, const char *Message,
5555

5656
// Run the interrupt handlers to make sure any special cleanups get done, in
5757
// particular that we remove files registered with RemoveFileOnSignal.
58-
llvm::sys::RunInterruptHandlers();
58+
llvm::sys::RunInterruptHandlers(/*ExecuteSignalHandlers=*/true);
5959

6060
// We cannot recover from llvm errors. When reporting a fatal error, exit
6161
// with status 70 to generate crash diagnostics. For BSD systems this is

clang/tools/driver/cc1_main.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ static void LLVMErrorHandler(void *UserData, const char *Message,
7272

7373
// Run the interrupt handlers to make sure any special cleanups get done, in
7474
// particular that we remove files registered with RemoveFileOnSignal.
75-
llvm::sys::RunInterruptHandlers();
75+
llvm::sys::RunInterruptHandlers(/*ExecuteSignalHandlers=*/true);
7676

7777
// We cannot recover from llvm errors. When reporting a fatal error, exit
7878
// with status 70 to generate crash diagnostics. For BSD systems this is

lld/test/ELF/lto/ltopasses-custom.ll

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,18 @@ define void @barrier() {
2424
; ATOMIC-NEXT: ret void
2525

2626
; Check that invalid passes are rejected gracefully.
27-
; RUN: env LLD_IN_TEST=1 not --crash ld.lld -m elf_x86_64 %t.o -o /dev/null \
27+
; The --implicit-check-not arguments verify that no crash-style output is shown.
28+
; RUN: env LLD_IN_TEST=1 not ld.lld -m elf_x86_64 %t.o -o /dev/null \
2829
; RUN: --lto-newpm-passes=iamnotapass -shared 2>&1 | \
29-
; RUN: FileCheck %s --check-prefix=INVALID
30+
; RUN: FileCheck %s --check-prefix=INVALID \
31+
; RUN: --ignore-case --implicit-check-not=bug --implicit-check-not=crash
3032
; INVALID: unable to parse pass pipeline description 'iamnotapass': unknown pass name 'iamnotapass'
3133

3234
; Check that invalid AA pipelines are rejected gracefully.
33-
; RUN: env LLD_IN_TEST=1 not --crash ld.lld -m elf_x86_64 %t.o -o /dev/null \
35+
; The --implicit-check-not arguments verify that no crash-style output is shown.
36+
; RUN: env LLD_IN_TEST=1 not ld.lld -m elf_x86_64 %t.o -o /dev/null \
3437
; RUN: --lto-newpm-passes=globaldce --lto-aa-pipeline=patatino \
3538
; RUN: -shared 2>&1 | \
36-
; RUN: FileCheck %s --check-prefix=INVALIDAA
39+
; RUN: FileCheck %s --check-prefix=INVALIDAA \
40+
; RUN: --ignore-case --implicit-check-not=bug --implicit-check-not=crash
3741
; INVALIDAA: unknown alias analysis name 'patatino'

llvm/docs/ReleaseNotes.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,9 @@ Changes to LLVM infrastructure
8080
* Added the support for ``fmaximum`` and ``fminimum`` in ``atomicrmw`` instruction. The
8181
comparison is expected to match the behavior of ``llvm.maximum.*`` and
8282
``llvm.minimum.*`` respectively.
83+
* On Windows, fatal usage errors no longer invoke LLVM's signal handlers.
84+
As a result, the default "please report a bug" message from the `PrettyStackTrace`
85+
signal handler is no longer emitted.
8386

8487
Changes to building LLVM
8588
------------------------

llvm/include/llvm/Support/Signals.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ namespace sys {
2626

2727
/// This function runs all the registered interrupt handlers, including the
2828
/// removal of files registered by RemoveFileOnSignal.
29-
LLVM_ABI void RunInterruptHandlers();
29+
LLVM_ABI void RunInterruptHandlers(bool ExecuteSignalHandlers);
3030

3131
/// This function registers signal handlers to ensure that if a signal gets
3232
/// delivered that the named file is removed.

llvm/lib/LTO/LTOBackend.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -290,8 +290,8 @@ static void runNewPMPasses(const Config &Conf, Module &Mod, TargetMachine *TM,
290290
if (!Conf.AAPipeline.empty()) {
291291
AAManager AA;
292292
if (auto Err = PB.parseAAPipeline(AA, Conf.AAPipeline)) {
293-
report_fatal_error(Twine("unable to parse AA pipeline description '") +
294-
Conf.AAPipeline + "': " + toString(std::move(Err)));
293+
reportFatalUsageError(Twine("unable to parse AA pipeline description '") +
294+
Conf.AAPipeline + "': " + toString(std::move(Err)));
295295
}
296296
// Register the AA manager first so that our version is the one used.
297297
FAM.registerPass([&] { return std::move(AA); });
@@ -331,8 +331,9 @@ static void runNewPMPasses(const Config &Conf, Module &Mod, TargetMachine *TM,
331331
// Parse a custom pipeline if asked to.
332332
if (!Conf.OptPipeline.empty()) {
333333
if (auto Err = PB.parsePassPipeline(MPM, Conf.OptPipeline)) {
334-
report_fatal_error(Twine("unable to parse pass pipeline description '") +
335-
Conf.OptPipeline + "': " + toString(std::move(Err)));
334+
reportFatalUsageError(
335+
Twine("unable to parse pass pipeline description '") +
336+
Conf.OptPipeline + "': " + toString(std::move(Err)));
336337
}
337338
} else if (IsThinLTO) {
338339
MPM.addPass(PB.buildThinLTODefaultPipeline(OL, ImportSummary));

llvm/lib/Support/ErrorHandling.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ void llvm::report_fatal_error(const Twine &Reason, bool GenCrashDiag) {
118118
// If we reached here, we are failing ungracefully. Run the interrupt handlers
119119
// to make sure any special cleanups get done, in particular that we remove
120120
// files registered with RemoveFileOnSignal.
121-
sys::RunInterruptHandlers();
121+
sys::RunInterruptHandlers(GenCrashDiag);
122122

123123
if (GenCrashDiag)
124124
abort();

llvm/lib/Support/Unix/Signals.inc

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -425,7 +425,9 @@ static void InfoSignalHandler(int Sig) {
425425
CurrentInfoFunction();
426426
}
427427

428-
void llvm::sys::RunInterruptHandlers() { RemoveFilesToRemove(); }
428+
void llvm::sys::RunInterruptHandlers(bool /*ExecuteSignalHandlers*/) {
429+
RemoveFilesToRemove();
430+
}
429431

430432
void llvm::sys::SetInterruptFunction(void (*IF)()) {
431433
InterruptFunction.exchange(IF);

llvm/lib/Support/Windows/Signals.inc

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -634,13 +634,13 @@ static void Cleanup(bool ExecuteSignalHandlers) {
634634
LeaveCriticalSection(&CriticalSection);
635635
}
636636

637-
void llvm::sys::RunInterruptHandlers() {
637+
void llvm::sys::RunInterruptHandlers(bool ExecuteSignalHandlers) {
638638
// The interrupt handler may be called from an interrupt, but it may also be
639639
// called manually (such as the case of report_fatal_error with no registered
640640
// error handler). We must ensure that the critical section is properly
641641
// initialized.
642642
InitializeThreading();
643-
Cleanup(true);
643+
Cleanup(ExecuteSignalHandlers);
644644
}
645645

646646
/// Find the Windows Registry Key for a given location.
@@ -847,7 +847,7 @@ void sys::CleanupOnSignal(uintptr_t Context) {
847847
}
848848

849849
static LONG WINAPI LLVMUnhandledExceptionFilter(LPEXCEPTION_POINTERS ep) {
850-
Cleanup(true);
850+
Cleanup(/*ExecuteSignalHandlers=*/true);
851851

852852
// Write out the exception code.
853853
if (ep && ep->ExceptionRecord)
@@ -887,7 +887,7 @@ static BOOL WINAPI LLVMConsoleCtrlHandler(DWORD dwCtrlType) {
887887
// This function is only ever called when a CTRL-C or similar control signal
888888
// is fired. Killing a process in this way is normal, so don't trigger the
889889
// signal handlers.
890-
Cleanup(false);
890+
Cleanup(/*ExecuteSignalHandlers=*/false);
891891

892892
// If an interrupt function has been set, go and run one it; otherwise,
893893
// the process dies.

llvm/lib/TableGen/Error.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ static void PrintMessage(ArrayRef<SMLoc> Loc, SourceMgr::DiagKind Kind,
4343
// Run file cleanup handlers and then exit fatally (with non-zero exit code).
4444
[[noreturn]] inline static void fatal_exit() {
4545
// The following call runs the file cleanup handlers.
46-
sys::RunInterruptHandlers();
46+
sys::RunInterruptHandlers(/*ExecuteSignalHandlers=*/true);
4747
std::exit(1);
4848
}
4949

llvm/test/tools/llvm-lto2/X86/pipeline.ll

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,13 @@ define void @patatino() {
2828
; CUSTOM-NEXT: }
2929

3030
; Check that invalid pipelines are caught as errors.
31-
; RUN: not --crash llvm-lto2 run %t1.bc -o %t.o \
31+
; RUN: not llvm-lto2 run %t1.bc -o %t.o \
3232
; RUN: -r %t1.bc,patatino,px -opt-pipeline foogoo 2>&1 | \
3333
; RUN: FileCheck %s --check-prefix=ERR
3434

3535
; ERR: LLVM ERROR: unable to parse pass pipeline description 'foogoo': unknown pass name 'foogoo'
3636

37-
; RUN: not --crash llvm-lto2 run %t1.bc -o %t.o \
37+
; RUN: not llvm-lto2 run %t1.bc -o %t.o \
3838
; RUN: -r %t1.bc,patatino,px -aa-pipeline patatino \
3939
; RUN: -opt-pipeline lower-atomic 2>&1 | \
4040
; RUN: FileCheck %s --check-prefix=AAERR

mlir/tools/mlir-tblgen/OpFormatGen.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3836,7 +3836,7 @@ void mlir::tblgen::generateOpFormat(const Operator &constOp, OpClass &opClass,
38363836
// Exit the process if format errors are treated as fatal.
38373837
if (formatErrorIsFatal) {
38383838
// Invoke the interrupt handlers to run the file cleanup handlers.
3839-
llvm::sys::RunInterruptHandlers();
3839+
llvm::sys::RunInterruptHandlers(/*ExecuteSignalHandlers=*/true);
38403840
std::exit(1);
38413841
}
38423842
return;

0 commit comments

Comments
 (0)