blob: 26c16160c60d7ab6b0a60ba6eb218a0d5dd41fe7 [file] [log] [blame]
// Copyright 2023 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <stdio.h>
#include <sys/wait.h>
#include <unistd.h>
#include <thread>
#include <gtest/gtest.h>
#include "src/starnix/tests/syscalls/cpp/test_helper.h"
TEST(AbortTest, Abort) {
test_helper::ForkHelper helper;
helper.ExpectSignal(SIGABRT);
helper.OnlyWaitForForkedChildren();
helper.RunInForkedProcess([] { abort(); });
ASSERT_TRUE(helper.WaitForChildren());
}
TEST(AbortTest, AbortFromChildThread) {
test_helper::ForkHelper helper;
helper.ExpectSignal(SIGABRT);
helper.OnlyWaitForForkedChildren();
helper.RunInForkedProcess([] {
volatile bool done = false;
std::thread child_thread([] { abort(); });
// Spin in userspace forever to verify that we can kick out of restricted
// mode even when not executing any syscalls.
while (!done) {
// This loop issues a volatile load on each iteration which is considered
// progress by C++ even though it has no practical effect:
// http://eel.is/c++draft/basic.exec#intro.progress
}
ASSERT_TRUE(false) << "Should not be reached";
});
ASSERT_TRUE(helper.WaitForChildren());
}
namespace {
void SigQuitHandler(int signum) { abort(); }
} // namespace
TEST(AbortTest, AbortFromSighandler) {
test_helper::ForkHelper helper;
helper.ExpectSignal(SIGABRT);
helper.OnlyWaitForForkedChildren();
helper.RunInForkedProcess([] {
struct sigaction sa{};
sa.sa_handler = SigQuitHandler;
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
SAFE_SYSCALL(sigaction(SIGQUIT, &sa, nullptr));
raise(SIGQUIT);
});
ASSERT_TRUE(helper.WaitForChildren());
}
namespace {
void SigUsr2Handler(int signum) { abort(); }
void SigUsr1Handler(int signum) { raise(SIGUSR2); }
} // namespace
TEST(AbortTest, AbortFromNestedSighandler) {
test_helper::ForkHelper helper;
helper.ExpectSignal(SIGABRT);
helper.OnlyWaitForForkedChildren();
helper.RunInForkedProcess([] {
struct sigaction sa{};
sa.sa_handler = SigUsr1Handler;
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
SAFE_SYSCALL(sigaction(SIGUSR1, &sa, nullptr));
sa.sa_handler = SigUsr2Handler;
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
SAFE_SYSCALL(sigaction(SIGUSR2, &sa, nullptr));
raise(SIGUSR1);
});
ASSERT_TRUE(helper.WaitForChildren());
}