Skip to content

Commit

Permalink
LibC: Implement pthread_cancel
Browse files Browse the repository at this point in the history
  • Loading branch information
timschumi authored and bgianfo committed Jul 22, 2022
1 parent 1269ce0 commit 899fd74
Show file tree
Hide file tree
Showing 5 changed files with 71 additions and 4 deletions.
1 change: 1 addition & 0 deletions Kernel/Thread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -871,6 +871,7 @@ static DefaultSignalAction default_signal_action(u8 signal)
case SIGIO:
case SIGPROF:
case SIGTERM:
case SIGCANCEL:
return DefaultSignalAction::Terminate;
case SIGCHLD:
case SIGURG:
Expand Down
23 changes: 23 additions & 0 deletions Userland/Libraries/LibC/bits/pthread_cancel.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
* Copyright (c) 2022, the SerenityOS developers.
*
* SPDX-License-Identifier: BSD-2-Clause
*/

#pragma once

#include <sys/cdefs.h>
#include <sys/types.h>

__BEGIN_DECLS

// This is our hook for cancellation points.
#ifdef _DYNAMIC_LOADER
inline void __pthread_maybe_cancel(void)
{
}
#else
void __pthread_maybe_cancel(void);
#endif

__END_DECLS
46 changes: 44 additions & 2 deletions Userland/Libraries/LibC/pthread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include <AK/StdLibExtras.h>
#include <Kernel/API/Syscall.h>
#include <LibSystem/syscall.h>
#include <bits/pthread_cancel.h>
#include <bits/pthread_integration.h>
#include <errno.h>
#include <limits.h>
Expand Down Expand Up @@ -51,6 +52,8 @@ struct CleanupHandler {

static thread_local SinglyLinkedList<CleanupHandler> cleanup_handlers;

static __thread bool pending_cancellation = false;

extern "C" {

[[noreturn]] static void exit_thread(void* code, void* stack_location, size_t stack_size)
Expand Down Expand Up @@ -154,6 +157,21 @@ void pthread_exit(void* value_ptr)
pthread_exit_without_cleanup_handlers(value_ptr);
}

void __pthread_maybe_cancel()
{
// Check if we have cancellations enabled.
if (s_thread_cancel_state != PTHREAD_CANCEL_ENABLE)
return;

// Check if a cancellation request is pending.
if (!pending_cancellation)
return;

// Exit the thread via `pthread_exit`. This handles passing the
// return value and calling the cleanup handlers for us.
pthread_exit(PTHREAD_CANCELED);
}

// https://pubs.opengroup.org/onlinepubs/009695399/functions/pthread_cleanup_push.html
void pthread_cleanup_push(void (*routine)(void*), void* arg)
{
Expand Down Expand Up @@ -481,11 +499,35 @@ int pthread_setschedparam([[maybe_unused]] pthread_t thread, [[maybe_unused]] in
return 0;
}

static void pthread_cancel_signal_handler(int signal)
{
// SIGCANCEL is a custom signal that is beyond the usual range of signal numbers.
// Let's make sure we know about it in case we still end up in here, but the signal
// number is being mangled.
VERIFY(signal == SIGCANCEL);

// Note: We don't handle PTHREAD_CANCEL_ASYNCHRONOUS any different from PTHREAD_CANCEL_DEFERRED,
// since ASYNCHRONOUS just means that the thread can be cancelled at any time (instead of just
// at the next cancellation point) and it seems to be generally discouraged to use it at all.
pending_cancellation = true;
}

// https://pubs.opengroup.org/onlinepubs/009695399/functions/pthread_cancel.html
// NOTE: libgcc expects this function to exist in libpthread, even if it is not implemented.
int pthread_cancel(pthread_t)
int pthread_cancel(pthread_t thread)
{
TODO();
// Set up our signal handler, which listens on SIGCANCEL and flips the cancellation indicator.
// Note that signal handlers are shared across the whole process, so we can just set that up at any time.
static bool set_up_cancel_handler = false;

if (!set_up_cancel_handler) {
struct sigaction act = {};
act.sa_handler = pthread_cancel_signal_handler;
sigaction(SIGCANCEL, &act, nullptr);
set_up_cancel_handler = true;
}

return pthread_kill(thread, SIGCANCEL);
}

int pthread_setname_np(pthread_t thread, char const* name)
Expand Down
2 changes: 1 addition & 1 deletion Userland/Libraries/LibC/pthread.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ int pthread_attr_destroy(pthread_attr_t*);
#define PTHREAD_CREATE_JOINABLE 0
#define PTHREAD_CREATE_DETACHED 1

#define PTHREAD_CANCELED (-1)
#define PTHREAD_CANCELED ((void*)-1)

int pthread_attr_getdetachstate(pthread_attr_t const*, int*);
int pthread_attr_setdetachstate(pthread_attr_t*, int);
Expand Down
3 changes: 2 additions & 1 deletion Userland/Libraries/LibC/signal_numbers.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,5 @@
#define SIGIO 29
#define SIGINFO 30
#define SIGSYS 31
#define NSIG 32
#define SIGCANCEL 32
#define NSIG 33

0 comments on commit 899fd74

Please sign in to comment.