NetBSD-Bugs archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
lib/59135: PTHREAD_CANCEL_ASYNCHRONOUS doesn't do much
>Number: 59135
>Category: lib
>Synopsis: PTHREAD_CANCEL_ASYNCHRONOUS doesn't do much
>Confidential: no
>Severity: serious
>Priority: medium
>Responsible: lib-bug-people
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Wed Mar 05 16:40:01 +0000 2025
>Originator: Taylor R Campbell
>Release: current, 10, 9, ...
>Organization:
The PthreadBSD Foun
>Environment:
>Description:
Under POSIX, when a thread has asynchronous cancellation configured with pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, ...), cancellation should be able to happen at any time, not just at cancellation points:
> Each thread maintains its own cancelability state, which may be encoded in two bits:
> 1. Cancelability-Enable: ...
> 2. Cancelability Type: When cancelability is enabled and the cancelability type is PTHREAD_CANCEL_ASYNCHRONOUS (as defined in <pthread.h>), new or pending cancellation requests may be acted upon at any time. When cancelability is enabled and the cancelability type is PTHREAD_CANCEL_DEFERRED (as defined in <pthread.h>), cancellation requests are held pending until a cancellation point (see below) is reached....
However, NetBSD's libpthread doesn't really do much with PTHREAD_CANCEL_ASYNCHRONOUS.
>How-To-Repeat:
#include <err.h>
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
static void
cleanup(void *cookie)
{
fprintf(stderr, "cleanup\n");
}
static void *
thread(void *cookie)
{
pthread_barrier_t *bar = cookie;
int error;
error = pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
if (error)
errc(1, error, "pthread_setcanceltype");
pthread_cleanup_push(cleanup, NULL);
fprintf(stderr, "loop forever\n");
(void)pthread_barrier_wait(bar);
for (;;) {
__asm("");
}
pthread_cleanup_pop(0);
return NULL;
}
int
main(void)
{
pthread_barrier_t bar;
pthread_t t;
int error;
error = pthread_barrier_init(&bar, NULL, 2);
if (error)
errc(1, error, "pthread_barrier_init");
fprintf(stderr, "create thread\n");
error = pthread_create(&t, NULL, &thread, &bar);
if (error)
errc(1, error, "pthread_create");
(void)pthread_barrier_wait(&bar);
fprintf(stderr, "cancel\n");
error = pthread_cancel(t);
if (error)
errc(1, error, "pthread_cancel");
(void)alarm(1);
error = pthread_join(t, NULL);
if (error)
errc(1, error, "pthread_join");
(void)alarm(0);
fprintf(stderr, "ok\n");
return 0;
}
>Fix:
1. Invent a new signal, say SIGCANCEL.
2. Teach libc's signal/sigaction/sigprocmask stubs to pretend it doesn't exist.
3. Teach libpthread to set up a SIGCANCEL handler that does pthread_cancel as appropriate.
4. Shake out all the bugs.
5. Shake out some more bugs.
6. ???
7. Profit!
8. ...just one or two more bugs
Home |
Main Index |
Thread Index |
Old Index