Przeglądaj źródła

LibPthread+Kernel: Add pthread_kill() and the thread_kill syscall

Ali Mohammad Pur 4 lat temu
rodzic
commit
e37f9fa7db

+ 2 - 1
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 {
 

+ 1 - 0
Kernel/Process.h

@@ -385,6 +385,7 @@ public:
     KResultOr<FlatPtr> sys$detach_thread(pid_t tid);
     KResultOr<FlatPtr> sys$set_thread_name(pid_t tid, Userspace<const char*> buffer, size_t buffer_size);
     KResultOr<FlatPtr> sys$get_thread_name(pid_t tid, Userspace<char*> buffer, size_t buffer_size);
+    KResultOr<FlatPtr> sys$kill_thread(pid_t tid, int signal);
     KResultOr<FlatPtr> sys$rename(Userspace<const Syscall::SC_rename_params*>);
     KResultOr<FlatPtr> sys$mknod(Userspace<const Syscall::SC_mknod_params*>);
     KResultOr<FlatPtr> sys$halt();

+ 21 - 0
Kernel/Syscalls/thread.cpp

@@ -159,6 +159,27 @@ KResultOr<FlatPtr> Process::sys$join_thread(pid_t tid, Userspace<void**> exit_va
     return 0;
 }
 
+KResultOr<FlatPtr> 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<FlatPtr> Process::sys$set_thread_name(pid_t tid, Userspace<const char*> user_name, size_t user_name_length)
 {
     REQUIRE_PROMISE(stdio);

+ 6 - 0
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);

+ 40 - 1
Userland/Utilities/tt.cpp

@@ -7,6 +7,7 @@
 #include <LibCore/ArgsParser.h>
 #include <errno.h>
 #include <pthread.h>
+#include <signal_numbers.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -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;
+}