From: Waldemar Kozaczuk <jwkozac...@gmail.com>
Committer: Nadav Har'El <n...@scylladb.com>
Branch: master

syscalls: minimally implement tgkill

The golang applications use the tgkill syscall to implement the
raise() function as the issue #1047 describes. The raise() function
is then used to propagate SIGTERM signal to the process when
Ctrl-C is pressed.

For that reason this patch adds very basic implementation
of the tgkill syscall. More specifically it only handles the case
where tpid specifies current process or -1 and tid specifies the current
thread of the caller which in essence is what Golang raise() passes.
In this case the tgkill syscall implementation delegates to kill()
otherwise it returns failure.

This patch also modifies the implementation of the pthread_kill()
to make it consistent with the implementation of the tgkill syscall.
The pthread_kill is actually called by raise() (see libc/pthread.cc)
so just like with tgkill, we check if specified pthread_t is equal to
the current thread and in such case we delegate to kill().

Lastly this patch enhances tst-kill.cc to test raise() and
pthread_kill().

Refs #1047

Signed-off-by: Waldemar Kozaczuk <jwkozac...@gmail.com>
Message-Id: <20210525050253.1141211-2-jwkozac...@gmail.com>

---
diff --git a/libc/pthread.cc b/libc/pthread.cc
--- a/libc/pthread.cc
+++ b/libc/pthread.cc
@@ -995,8 +995,19 @@ int pthread_getschedparam(pthread_t thread, int *policy,
 
 int pthread_kill(pthread_t thread, int sig)
 {
-    WARN_STUBBED();
+    // We are assuming that if pthread_kill() is called with thread
+    // equal to pthread_self(), then most likely it was called by
+    // raise() (see below) so we simply delegate to kill().
+    // This an approximation as it reality multithreaded apps
+    // may actually send signal to the current thread by directly
+    // calling pthread_kill() for a reason and then thread specific mask
+    // would apply, etc. But OSv does not really support sending signals to
+    // specific threads so we are silently ignoring such case for now.
+    if (thread == current_pthread) {
+        return kill(getpid(), sig);
+    }
 
+    WARN_STUBBED();
     return EINVAL;
 }
 
diff --git a/linux.cc b/linux.cc
--- a/linux.cc
+++ b/linux.cc
@@ -371,6 +371,22 @@ static int pselect6(int nfds, fd_set *readfds, fd_set 
*writefds,
     return pselect(nfds, readfds, writefds, exceptfds, timeout_ts, NULL);
 }
 
+static int tgkill(int tgid, int tid, int sig)
+{
+    //
+    // Given OSv supports sigle process only, we only support this syscall
+    // when thread group id is self (getpid()) or -1 (see 
https://linux.die.net/man/2/tgkill)
+    // AND tid points to the current thread (caller)
+    // Ideally we would want to delegate to pthread_kill() but there is no
+    // easy way to map tgid to pthread_t so we directly delegate to kill().
+    if ((tgid == -1 || tgid == getpid()) && (tid == gettid())) {
+        return kill(tgid, sig);
+    }
+
+    errno = ENOSYS;
+    return -1;
+}
+
 long syscall(long number, ...)
 {
     // Save FPU state and restore it at the end of this function
@@ -451,6 +467,7 @@ long syscall(long number, ...)
     SYSCALL2(mkdir, char*, mode_t);
 #endif
     SYSCALL3(mkdirat, int, char*, mode_t);
+    SYSCALL3(tgkill, int, int, int);
     }
 
     debug_always("syscall(): unimplemented system call %d\n", number);
diff --git a/tests/tst-kill.cc b/tests/tst-kill.cc
--- a/tests/tst-kill.cc
+++ b/tests/tst-kill.cc
@@ -13,6 +13,7 @@
 #include <stdio.h>
 #include <unistd.h>
 #include <errno.h>
+#include <pthread.h>
 
 int tests = 0, fails = 0;
 
@@ -98,6 +99,10 @@ int main(int ac, char** av)
     r = kill(17171717, 0);
     report(r == -1 && errno == ESRCH, "kill of non-existant process");
 
+    report(raise(0) == 0, "raise() should succeed");
+    report(pthread_kill(pthread_self(), 0) == 0, "pthread_kill() should 
succeed with current thread");
+    report(pthread_kill((pthread_t)(-1), 0) == EINVAL, "pthread_kill() should 
fail for thread different than current one");
+
     // Test alarm();
     global = 0;
     sr = signal(SIGALRM, handler1);

-- 
You received this message because you are subscribed to the Google Groups "OSv 
Development" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to osv-dev+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/osv-dev/000000000000b7fd1505c322fa00%40google.com.

Reply via email to