diff --git a/Source/Tools/LinuxEmulation/LinuxSyscalls/Syscalls/Thread.cpp b/Source/Tools/LinuxEmulation/LinuxSyscalls/Syscalls/Thread.cpp index 7ce392b398..3c93f76935 100644 --- a/Source/Tools/LinuxEmulation/LinuxSyscalls/Syscalls/Thread.cpp +++ b/Source/Tools/LinuxEmulation/LinuxSyscalls/Syscalls/Thread.cpp @@ -414,9 +414,10 @@ void RegisterThread(FEX::HLE::SyscallHandler* Handler) { } ThreadObject->StatusCode = status; - FEX::HLE::_SyscallHandler->TM.StopThread(ThreadObject); - - return 0; + FEX::HLE::_SyscallHandler->TM.DestroyThread(ThreadObject, true); + syscall(SYSCALL_DEF(exit), status); + // This will never be reached + std::terminate(); }); REGISTER_SYSCALL_IMPL_FLAGS(prctl, SyscallFlags::OPTIMIZETHROUGH | SyscallFlags::NOSYNCSTATEONENTRY, diff --git a/unittests/FEXLinuxTests/tests/syscalls/syscall_exit.cpp b/unittests/FEXLinuxTests/tests/syscalls/syscall_exit.cpp new file mode 100644 index 0000000000..4239fdeff4 --- /dev/null +++ b/unittests/FEXLinuxTests/tests/syscalls/syscall_exit.cpp @@ -0,0 +1,35 @@ +#include + +#include +#include +#include + +TEST_CASE("fork - exit") { + int child_pid = ::fork(); + if (child_pid == 0) { + ::syscall(SYS_exit, 1); + // unreachable + std::terminate(); + } else { + int status {}; + int exited_child = ::waitpid(child_pid, &status, 0); + bool exited = WIFEXITED(status); + REQUIRE(WIFEXITED(status) == 1); + CHECK(WEXITSTATUS(status) == 1); + } +} + +TEST_CASE("fork - signal") { + int child_pid = ::fork(); + if (child_pid == 0) { + ::syscall(SYS_tgkill, ::getpid(), ::gettid(), SIGKILL); + // unreachable + std::terminate(); + } else { + int status {}; + int exited_child = ::waitpid(child_pid, &status, 0); + bool exited = WIFEXITED(status); + REQUIRE(WIFSIGNALED(status) == 1); + CHECK(WTERMSIG(status) == SIGKILL); + } +}