diff --git a/Kernel/API/Syscall.h b/Kernel/API/Syscall.h index 36c28c2611..88854ef726 100644 --- a/Kernel/API/Syscall.h +++ b/Kernel/API/Syscall.h @@ -179,7 +179,8 @@ namespace Kernel { S(readv) \ S(emuctl) \ S(statvfs) \ - S(fstatvfs) + S(fstatvfs) \ + S(kill_thread) namespace Syscall { diff --git a/Kernel/Process.h b/Kernel/Process.h index 4a90db4fc2..8a0d42c8a5 100644 --- a/Kernel/Process.h +++ b/Kernel/Process.h @@ -385,6 +385,7 @@ public: KResultOr sys$detach_thread(pid_t tid); KResultOr sys$set_thread_name(pid_t tid, Userspace buffer, size_t buffer_size); KResultOr sys$get_thread_name(pid_t tid, Userspace buffer, size_t buffer_size); + KResultOr sys$kill_thread(pid_t tid, int signal); KResultOr sys$rename(Userspace); KResultOr sys$mknod(Userspace); KResultOr sys$halt(); diff --git a/Kernel/Syscalls/thread.cpp b/Kernel/Syscalls/thread.cpp index dcaebc3d95..b543568749 100644 --- a/Kernel/Syscalls/thread.cpp +++ b/Kernel/Syscalls/thread.cpp @@ -159,6 +159,27 @@ KResultOr Process::sys$join_thread(pid_t tid, Userspace exit_va return 0; } +KResultOr Process::sys$kill_thread(pid_t tid, int signal) +{ + REQUIRE_PROMISE(thread); + + if (signal < 0 || signal >= 32) + return EINVAL; + + auto thread = Thread::from_tid(tid); + if (!thread || thread->pid() != pid()) + return ESRCH; + + auto process = Process::current(); + if (!process) + return ESRCH; + + if (signal != 0) + thread->send_signal(signal, process); + + return 0; +} + KResultOr Process::sys$set_thread_name(pid_t tid, Userspace user_name, size_t user_name_length) { REQUIRE_PROMISE(stdio); diff --git a/Userland/Libraries/LibPthread/pthread.cpp b/Userland/Libraries/LibPthread/pthread.cpp index 18b758a430..8037f2fac8 100644 --- a/Userland/Libraries/LibPthread/pthread.cpp +++ b/Userland/Libraries/LibPthread/pthread.cpp @@ -151,6 +151,12 @@ int pthread_join(pthread_t thread, void** exit_value_ptr) __RETURN_PTHREAD_ERROR(rc); } +int pthread_kill(pthread_t thread, int sig) +{ + int rc = syscall(SC_kill_thread, thread, sig); + __RETURN_PTHREAD_ERROR(rc); +} + int pthread_detach(pthread_t thread) { int rc = syscall(SC_detach_thread, thread); diff --git a/Userland/Utilities/tt.cpp b/Userland/Utilities/tt.cpp index bdf6c7e5af..49bbc66323 100644 --- a/Userland/Utilities/tt.cpp +++ b/Userland/Utilities/tt.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -19,6 +20,7 @@ static int priority_test(); static int stack_size_test(); static int staying_alive_test(); static int set_stack_test(); +static int kill_test(); int main(int argc, char** argv) { @@ -28,7 +30,7 @@ int main(int argc, char** argv) args_parser.set_general_help( "Exercise error-handling and edge-case paths of the execution environment " "(i.e., Kernel or UE) by doing unusual thread-related things."); - args_parser.add_positional_argument(test_name, "Test to run (m = mutex, d = detached, p = priority, s = stack size, t = simple thread test, x = set stack, nothing = join race)", "test-name", Core::ArgsParser::Required::No); + args_parser.add_positional_argument(test_name, "Test to run (m = mutex, d = detached, p = priority, s = stack size, t = simple thread test, x = set stack, k = kill, nothing = join race)", "test-name", Core::ArgsParser::Required::No); args_parser.parse(argc, argv); if (*test_name == 'm') @@ -43,6 +45,8 @@ int main(int argc, char** argv) return staying_alive_test(); if (*test_name == 'x') return set_stack_test(); + if (*test_name == 'k') + return kill_test(); if (*test_name != 'n') { args_parser.print_usage(stdout, argv[0]); return 1; @@ -372,3 +376,38 @@ int set_stack_test() return 0; } + +int kill_test() +{ + pthread_t thread_id; + int rc = pthread_create( + &thread_id, nullptr, [](void*) -> void* { + outln("I'm the secondary thread :^)"); + sleep(100); + outln("Secondary thread is still alive :^("); + pthread_exit((void*)0xDEADBEEF); + return nullptr; + }, + nullptr); + if (rc < 0) { + perror("pthread_create"); + return 1; + } + + int result = 0; + + sleep(1); + outln("I'm the main thread :^)"); + if (pthread_kill(thread_id, 0) != 0) { + perror("pthread_kill"); + result = 1; + } + + if (pthread_kill(thread_id, SIGKILL) != 0) { + perror("pthread_kill(SIGKILL)"); + result = 1; + } + + outln("Main thread exiting"); + return result; +}