Skip to content

Commit 5830e8e

Browse files
[llvm-exegesis] Use explicit error classes for different snippet crashes (#74210)
This patch switches to using explicit snippet crashes that contain more information about the specific type of error (like the address for a segmentation fault) that occurred. All these new error classes inherit from SnippetExecutionFailure to allow for easily grabbing all of them in addition to filtering for specific types using the standard LLVM error primitives.
1 parent 1c830b7 commit 5830e8e

File tree

6 files changed

+70
-26
lines changed

6 files changed

+70
-26
lines changed

llvm/test/tools/llvm-exegesis/X86/latency/subprocess-abnormal-exit-code.s

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
# REQUIRES: exegesis-can-measure-latency, x86_64-linux
22

3-
# RUN: llvm-exegesis -mtriple=x86_64-unknown-unknown -mode=latency -snippets-file=%s -execution-mode=subprocess | FileCheck %s
3+
# RUN: not llvm-exegesis -mtriple=x86_64-unknown-unknown -mode=latency -snippets-file=%s -execution-mode=subprocess 2>&1 | FileCheck %s
44

5-
# CHECK: error: 'Child benchmarking process exited with non-zero exit code: Child process returned with unknown exit code'
5+
# CHECK: llvm-exegesis error: Child benchmarking process exited with non-zero exit code: Child process returned with unknown exit code
66

77
movl $60, %eax
88
movl $127, %edi

llvm/test/tools/llvm-exegesis/X86/latency/subprocess-segfault.s

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
# RUN: llvm-exegesis -mtriple=x86_64-unknown-unknown -mode=latency -snippets-file=%s -execution-mode=subprocess | FileCheck %s
44

5-
# CHECK: error: 'The benchmarking subprocess sent unexpected signal: Segmentation fault'
5+
# CHECK: error: The snippet encountered a segmentation fault at address 10
66

7-
# LLVM-EXEGESIS-DEFREG RBX 0
7+
# LLVM-EXEGESIS-DEFREG RBX 10
88
movq (%rbx), %rax

llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -147,17 +147,16 @@ class InProcessFunctionExecutorImpl : public BenchmarkRunner::FunctionExecutor {
147147
CrashRecoveryContext::Disable();
148148
PS.reset();
149149
if (Crashed) {
150-
std::string Msg = "snippet crashed while running";
151150
#ifdef LLVM_ON_UNIX
152151
// See "Exit Status for Commands":
153152
// https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_xcu_chap02.html
154153
constexpr const int kSigOffset = 128;
155-
if (const char *const SigName = strsignal(CRC.RetCode - kSigOffset)) {
156-
Msg += ": ";
157-
Msg += SigName;
158-
}
159-
#endif
160-
return make_error<SnippetCrash>(std::move(Msg));
154+
return make_error<SnippetSignal>(CRC.RetCode - kSigOffset);
155+
#else
156+
// The exit code of the process on windows is not meaningful as a
157+
// signal, so simply pass in -1 as the signal into the error.
158+
return make_error<SnippetSignal>(-1);
159+
#endif // LLVM_ON_UNIX
161160
}
162161
}
163162

@@ -366,7 +365,7 @@ class SubProcessFunctionExecutorImpl
366365
return Error::success();
367366
}
368367
// The child exited, but not successfully
369-
return make_error<SnippetCrash>(
368+
return make_error<Failure>(
370369
"Child benchmarking process exited with non-zero exit code: " +
371370
childProcessExitCodeToString(ChildExitCode));
372371
}
@@ -379,9 +378,11 @@ class SubProcessFunctionExecutorImpl
379378
Twine(strerror(errno)));
380379
}
381380

382-
return make_error<SnippetCrash>(
383-
"The benchmarking subprocess sent unexpected signal: " +
384-
Twine(strsignal(ChildSignalInfo.si_signo)));
381+
if (ChildSignalInfo.si_signo == SIGSEGV)
382+
return make_error<SnippetSegmentationFault>(
383+
reinterpret_cast<intptr_t>(ChildSignalInfo.si_addr));
384+
385+
return make_error<SnippetSignal>(ChildSignalInfo.si_signo);
385386
}
386387

387388
void disableCoreDumps() const {

llvm/tools/llvm-exegesis/lib/Error.cpp

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@
88

99
#include "Error.h"
1010

11+
#ifdef LLVM_ON_UNIX
12+
#include <string.h>
13+
#endif // LLVM_ON_UNIX
14+
1115
namespace llvm {
1216
namespace exegesis {
1317

@@ -19,13 +23,27 @@ std::error_code ClusteringError::convertToErrorCode() const {
1923
return inconvertibleErrorCode();
2024
}
2125

22-
char SnippetCrash::ID;
23-
24-
void SnippetCrash::log(raw_ostream &OS) const { OS << Msg; }
26+
char SnippetExecutionFailure::ID;
2527

26-
std::error_code SnippetCrash::convertToErrorCode() const {
28+
std::error_code SnippetExecutionFailure::convertToErrorCode() const {
2729
return inconvertibleErrorCode();
2830
}
2931

32+
char SnippetSegmentationFault::ID;
33+
34+
void SnippetSegmentationFault::log(raw_ostream &OS) const {
35+
OS << "The snippet encountered a segmentation fault at address "
36+
<< Twine::utohexstr(Address);
37+
}
38+
39+
char SnippetSignal::ID;
40+
41+
void SnippetSignal::log(raw_ostream &OS) const {
42+
OS << "snippet crashed while running";
43+
#ifdef LLVM_ON_UNIX
44+
OS << ": " << strsignal(SignalNumber);
45+
#endif // LLVM_ON_UNIX
46+
}
47+
3048
} // namespace exegesis
3149
} // namespace llvm

llvm/tools/llvm-exegesis/lib/Error.h

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -36,19 +36,44 @@ class ClusteringError : public ErrorInfo<ClusteringError> {
3636
std::string Msg;
3737
};
3838

39-
// A class representing failures that happened during snippet execution.
40-
// Instead of terminating the program crashes are logged into the output.
41-
class SnippetCrash : public ErrorInfo<SnippetCrash> {
39+
// A class representing a non-descript snippet execution failure. This class
40+
// is designed to sub-classed into more specific failures that contain
41+
// additional data about the specific error that they represent. Instead of
42+
// halting the program, the errors are reported in the output.
43+
class SnippetExecutionFailure : public ErrorInfo<SnippetExecutionFailure> {
4244
public:
4345
static char ID;
44-
SnippetCrash(const Twine &S) : Msg(S.str()) {}
46+
47+
std::error_code convertToErrorCode() const override;
48+
};
49+
50+
// A class representing specifically segmentation faults that happen during
51+
// snippet execution.
52+
class SnippetSegmentationFault : public SnippetExecutionFailure {
53+
public:
54+
static char ID;
55+
SnippetSegmentationFault(intptr_t SegFaultAddress)
56+
: Address(SegFaultAddress){};
57+
58+
intptr_t getAddress() { return Address; }
4559

4660
void log(raw_ostream &OS) const override;
4761

48-
std::error_code convertToErrorCode() const override;
62+
private:
63+
intptr_t Address;
64+
};
65+
66+
// A class representing all other non-specific failures that happen during
67+
// snippet execution.
68+
class SnippetSignal : public SnippetExecutionFailure {
69+
public:
70+
static char ID;
71+
SnippetSignal(int Signal) : SignalNumber(Signal){};
72+
73+
void log(raw_ostream &OS) const override;
4974

5075
private:
51-
std::string Msg;
76+
int SignalNumber;
5277
};
5378

5479
} // namespace exegesis

llvm/tools/llvm-exegesis/llvm-exegesis.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -415,7 +415,7 @@ static void runBenchmarkConfigurations(
415415
if (Err) {
416416
// Errors from executing the snippets are fine.
417417
// All other errors are a framework issue and should fail.
418-
if (!Err.isA<SnippetCrash>()) {
418+
if (!Err.isA<SnippetExecutionFailure>()) {
419419
llvm::errs() << "llvm-exegesis error: " << toString(std::move(Err));
420420
exit(1);
421421
}

0 commit comments

Comments
 (0)