Skip to content

Commit

Permalink
[llvm-exegesis] Use explicit error classes for different snippet cras…
Browse files Browse the repository at this point in the history
…hes (llvm#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.
  • Loading branch information
boomanaiden154 authored Dec 12, 2023
1 parent 1c830b7 commit 5830e8e
Show file tree
Hide file tree
Showing 6 changed files with 70 additions and 26 deletions.
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# REQUIRES: exegesis-can-measure-latency, x86_64-linux

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

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

movl $60, %eax
movl $127, %edi
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

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

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

# LLVM-EXEGESIS-DEFREG RBX 0
# LLVM-EXEGESIS-DEFREG RBX 10
movq (%rbx), %rax
23 changes: 12 additions & 11 deletions llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -147,17 +147,16 @@ class InProcessFunctionExecutorImpl : public BenchmarkRunner::FunctionExecutor {
CrashRecoveryContext::Disable();
PS.reset();
if (Crashed) {
std::string Msg = "snippet crashed while running";
#ifdef LLVM_ON_UNIX
// See "Exit Status for Commands":
// https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_xcu_chap02.html
constexpr const int kSigOffset = 128;
if (const char *const SigName = strsignal(CRC.RetCode - kSigOffset)) {
Msg += ": ";
Msg += SigName;
}
#endif
return make_error<SnippetCrash>(std::move(Msg));
return make_error<SnippetSignal>(CRC.RetCode - kSigOffset);
#else
// The exit code of the process on windows is not meaningful as a
// signal, so simply pass in -1 as the signal into the error.
return make_error<SnippetSignal>(-1);
#endif // LLVM_ON_UNIX
}
}

Expand Down Expand Up @@ -366,7 +365,7 @@ class SubProcessFunctionExecutorImpl
return Error::success();
}
// The child exited, but not successfully
return make_error<SnippetCrash>(
return make_error<Failure>(
"Child benchmarking process exited with non-zero exit code: " +
childProcessExitCodeToString(ChildExitCode));
}
Expand All @@ -379,9 +378,11 @@ class SubProcessFunctionExecutorImpl
Twine(strerror(errno)));
}

return make_error<SnippetCrash>(
"The benchmarking subprocess sent unexpected signal: " +
Twine(strsignal(ChildSignalInfo.si_signo)));
if (ChildSignalInfo.si_signo == SIGSEGV)
return make_error<SnippetSegmentationFault>(
reinterpret_cast<intptr_t>(ChildSignalInfo.si_addr));

return make_error<SnippetSignal>(ChildSignalInfo.si_signo);
}

void disableCoreDumps() const {
Expand Down
26 changes: 22 additions & 4 deletions llvm/tools/llvm-exegesis/lib/Error.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@

#include "Error.h"

#ifdef LLVM_ON_UNIX
#include <string.h>
#endif // LLVM_ON_UNIX

namespace llvm {
namespace exegesis {

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

char SnippetCrash::ID;

void SnippetCrash::log(raw_ostream &OS) const { OS << Msg; }
char SnippetExecutionFailure::ID;

std::error_code SnippetCrash::convertToErrorCode() const {
std::error_code SnippetExecutionFailure::convertToErrorCode() const {
return inconvertibleErrorCode();
}

char SnippetSegmentationFault::ID;

void SnippetSegmentationFault::log(raw_ostream &OS) const {
OS << "The snippet encountered a segmentation fault at address "
<< Twine::utohexstr(Address);
}

char SnippetSignal::ID;

void SnippetSignal::log(raw_ostream &OS) const {
OS << "snippet crashed while running";
#ifdef LLVM_ON_UNIX
OS << ": " << strsignal(SignalNumber);
#endif // LLVM_ON_UNIX
}

} // namespace exegesis
} // namespace llvm
37 changes: 31 additions & 6 deletions llvm/tools/llvm-exegesis/lib/Error.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,19 +36,44 @@ class ClusteringError : public ErrorInfo<ClusteringError> {
std::string Msg;
};

// A class representing failures that happened during snippet execution.
// Instead of terminating the program crashes are logged into the output.
class SnippetCrash : public ErrorInfo<SnippetCrash> {
// A class representing a non-descript snippet execution failure. This class
// is designed to sub-classed into more specific failures that contain
// additional data about the specific error that they represent. Instead of
// halting the program, the errors are reported in the output.
class SnippetExecutionFailure : public ErrorInfo<SnippetExecutionFailure> {
public:
static char ID;
SnippetCrash(const Twine &S) : Msg(S.str()) {}

std::error_code convertToErrorCode() const override;
};

// A class representing specifically segmentation faults that happen during
// snippet execution.
class SnippetSegmentationFault : public SnippetExecutionFailure {
public:
static char ID;
SnippetSegmentationFault(intptr_t SegFaultAddress)
: Address(SegFaultAddress){};

intptr_t getAddress() { return Address; }

void log(raw_ostream &OS) const override;

std::error_code convertToErrorCode() const override;
private:
intptr_t Address;
};

// A class representing all other non-specific failures that happen during
// snippet execution.
class SnippetSignal : public SnippetExecutionFailure {
public:
static char ID;
SnippetSignal(int Signal) : SignalNumber(Signal){};

void log(raw_ostream &OS) const override;

private:
std::string Msg;
int SignalNumber;
};

} // namespace exegesis
Expand Down
2 changes: 1 addition & 1 deletion llvm/tools/llvm-exegesis/llvm-exegesis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -415,7 +415,7 @@ static void runBenchmarkConfigurations(
if (Err) {
// Errors from executing the snippets are fine.
// All other errors are a framework issue and should fail.
if (!Err.isA<SnippetCrash>()) {
if (!Err.isA<SnippetExecutionFailure>()) {
llvm::errs() << "llvm-exegesis error: " << toString(std::move(Err));
exit(1);
}
Expand Down

0 comments on commit 5830e8e

Please sign in to comment.