mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 17:37:37 +00:00
LibC: Implement pthread_cancel
This commit is contained in:
parent
1269ce0c35
commit
899fd74f8e
5 changed files with 71 additions and 4 deletions
|
@ -871,6 +871,7 @@ static DefaultSignalAction default_signal_action(u8 signal)
|
||||||
case SIGIO:
|
case SIGIO:
|
||||||
case SIGPROF:
|
case SIGPROF:
|
||||||
case SIGTERM:
|
case SIGTERM:
|
||||||
|
case SIGCANCEL:
|
||||||
return DefaultSignalAction::Terminate;
|
return DefaultSignalAction::Terminate;
|
||||||
case SIGCHLD:
|
case SIGCHLD:
|
||||||
case SIGURG:
|
case SIGURG:
|
||||||
|
|
23
Userland/Libraries/LibC/bits/pthread_cancel.h
Normal file
23
Userland/Libraries/LibC/bits/pthread_cancel.h
Normal file
|
@ -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
|
|
@ -12,6 +12,7 @@
|
||||||
#include <AK/StdLibExtras.h>
|
#include <AK/StdLibExtras.h>
|
||||||
#include <Kernel/API/Syscall.h>
|
#include <Kernel/API/Syscall.h>
|
||||||
#include <LibSystem/syscall.h>
|
#include <LibSystem/syscall.h>
|
||||||
|
#include <bits/pthread_cancel.h>
|
||||||
#include <bits/pthread_integration.h>
|
#include <bits/pthread_integration.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
@ -51,6 +52,8 @@ struct CleanupHandler {
|
||||||
|
|
||||||
static thread_local SinglyLinkedList<CleanupHandler> cleanup_handlers;
|
static thread_local SinglyLinkedList<CleanupHandler> cleanup_handlers;
|
||||||
|
|
||||||
|
static __thread bool pending_cancellation = false;
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
|
||||||
[[noreturn]] static void exit_thread(void* code, void* stack_location, size_t stack_size)
|
[[noreturn]] static void exit_thread(void* code, void* stack_location, size_t stack_size)
|
||||||
|
@ -154,6 +157,21 @@ void pthread_exit(void* value_ptr)
|
||||||
pthread_exit_without_cleanup_handlers(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
|
// https://pubs.opengroup.org/onlinepubs/009695399/functions/pthread_cleanup_push.html
|
||||||
void pthread_cleanup_push(void (*routine)(void*), void* arg)
|
void pthread_cleanup_push(void (*routine)(void*), void* arg)
|
||||||
{
|
{
|
||||||
|
@ -481,11 +499,35 @@ int pthread_setschedparam([[maybe_unused]] pthread_t thread, [[maybe_unused]] in
|
||||||
return 0;
|
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
|
// 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.
|
// 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)
|
int pthread_setname_np(pthread_t thread, char const* name)
|
||||||
|
|
|
@ -33,7 +33,7 @@ int pthread_attr_destroy(pthread_attr_t*);
|
||||||
#define PTHREAD_CREATE_JOINABLE 0
|
#define PTHREAD_CREATE_JOINABLE 0
|
||||||
#define PTHREAD_CREATE_DETACHED 1
|
#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_getdetachstate(pthread_attr_t const*, int*);
|
||||||
int pthread_attr_setdetachstate(pthread_attr_t*, int);
|
int pthread_attr_setdetachstate(pthread_attr_t*, int);
|
||||||
|
|
|
@ -38,4 +38,5 @@
|
||||||
#define SIGIO 29
|
#define SIGIO 29
|
||||||
#define SIGINFO 30
|
#define SIGINFO 30
|
||||||
#define SIGSYS 31
|
#define SIGSYS 31
|
||||||
#define NSIG 32
|
#define SIGCANCEL 32
|
||||||
|
#define NSIG 33
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue