ladybird/Userland/Libraries/LibTest/CrashTest.cpp
Liav A 1c0aa51684 Kernel+Userland: Remove the {get,set}_thread_name syscalls
These syscalls are not necessary on their own, and they give the false
impression that a caller could set or get the thread name of any process
in the system, which is not true.

Therefore, move the functionality of these syscalls to be options in the
prctl syscall, which makes it abundantly clear that these operations
could only occur from a running thread in a process that sees other
threads in that process only.
2023-08-25 11:51:52 +02:00

109 lines
2.9 KiB
C++

/*
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
* Copyright (c) 2019-2020, Shannon Booth <shannon@serenityos.org>
* Copyright (c) 2021, Brian Gianforcaro <bgianf@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <AK/Assertions.h>
#include <AK/Platform.h>
#include <LibTest/CrashTest.h>
#include <sys/wait.h>
#include <unistd.h>
#if !defined(AK_OS_MACOS) && !defined(AK_OS_EMSCRIPTEN)
# include <sys/prctl.h>
#endif
namespace Test {
Crash::Crash(DeprecatedString test_type, Function<Crash::Failure()> crash_function, int crash_signal)
: m_type(move(test_type))
, m_crash_function(move(crash_function))
, m_crash_signal(crash_signal)
{
}
bool Crash::run(RunType run_type)
{
outln("\x1B[33mTesting\x1B[0m: \"{}\"", m_type);
if (run_type == RunType::UsingCurrentProcess) {
return do_report(m_crash_function());
} else {
// Run the test in a child process so that we do not crash the crash program :^)
pid_t pid = fork();
if (pid < 0) {
perror("fork");
VERIFY_NOT_REACHED();
} else if (pid == 0) {
#if !defined(AK_OS_MACOS) && !defined(AK_OS_EMSCRIPTEN)
if (prctl(PR_SET_DUMPABLE, 0, 0, 0) < 0)
perror("prctl(PR_SET_DUMPABLE)");
#endif
exit((int)m_crash_function());
}
int status;
waitpid(pid, &status, 0);
if (WIFEXITED(status)) {
return do_report(Failure(WEXITSTATUS(status)));
}
if (WIFSIGNALED(status)) {
int signal = WTERMSIG(status);
VERIFY(signal > 0);
return do_report(signal);
}
VERIFY_NOT_REACHED();
}
}
bool Crash::do_report(Report report)
{
bool pass = false;
if (m_crash_signal == ANY_SIGNAL) {
pass = report.has<int>();
} else if (m_crash_signal == 0) {
pass = report.has<Failure>() && report.get<Failure>() == Failure::DidNotCrash;
} else if (m_crash_signal > 0) {
pass = report.has<int>() && report.get<int>() == m_crash_signal;
} else {
VERIFY_NOT_REACHED();
}
if (pass)
out("\x1B[32mPASS\x1B[0m: ");
else
out("\x1B[31mFAIL\x1B[0m: ");
report.visit(
[&](Failure const& failure) {
switch (failure) {
case Failure::DidNotCrash:
out("Did not crash");
break;
case Failure::UnexpectedError:
out("Unexpected error");
break;
default:
VERIFY_NOT_REACHED();
}
},
[&](int const& signal) {
out("Terminated with signal {}", signal);
});
if (!pass) {
if (m_crash_signal == ANY_SIGNAL) {
out(" while expecting any signal");
} else if (m_crash_signal > 0) {
out(" while expecting signal {}", m_crash_signal);
}
}
outln();
return pass;
}
}