Skip to content

Commit

Permalink
syscalls: minimally implement tgkill
Browse files Browse the repository at this point in the history
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 <[email protected]>
Message-Id: <[email protected]>
  • Loading branch information
wkozaczuk authored and nyh committed May 25, 2021
1 parent afe3af4 commit ce7620c
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 1 deletion.
13 changes: 12 additions & 1 deletion libc/pthread.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down
17 changes: 17 additions & 0 deletions linux.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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);
Expand Down
5 changes: 5 additions & 0 deletions tests/tst-kill.cc
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <pthread.h>

int tests = 0, fails = 0;

Expand Down Expand Up @@ -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);
Expand Down

0 comments on commit ce7620c

Please sign in to comment.