mirror of git://git.musl-libc.org/musl
new framework to inhibit thread cancellation when needed
with these small changes, libc functions which need to call functions which are cancellation points, but which themselves must not be cancellation points, can use the CANCELPT_INHIBIT and CANCELPT_RESUME macros to temporarily inhibit all cancellation.
This commit is contained in:
parent
918a40f257
commit
729cb49f52
|
@ -45,6 +45,8 @@ void __lockfile(FILE *);
|
||||||
#define CANCELPT_BEGIN CANCELPT(1)
|
#define CANCELPT_BEGIN CANCELPT(1)
|
||||||
#define CANCELPT_TRY CANCELPT(0)
|
#define CANCELPT_TRY CANCELPT(0)
|
||||||
#define CANCELPT_END CANCELPT(-1)
|
#define CANCELPT_END CANCELPT(-1)
|
||||||
|
#define CANCELPT_INHIBIT CANCELPT(2)
|
||||||
|
#define CANCELPT_RESUME CANCELPT(-2)
|
||||||
|
|
||||||
extern char **__environ;
|
extern char **__environ;
|
||||||
#define environ __environ
|
#define environ __environ
|
||||||
|
|
|
@ -57,9 +57,19 @@ static void cancel_handler(int sig, siginfo_t *si, void *ctx)
|
||||||
static void cancelpt(int x)
|
static void cancelpt(int x)
|
||||||
{
|
{
|
||||||
struct pthread *self = __pthread_self();
|
struct pthread *self = __pthread_self();
|
||||||
if (self->canceldisable) return;
|
switch (x) {
|
||||||
if ((self->cancelpoint+=x)==1 && x>=0 && self->cancel)
|
case 1:
|
||||||
docancel(self);
|
self->cancelpoint++;
|
||||||
|
case 0:
|
||||||
|
if (self->cancel && self->cancelpoint==1 && !self->canceldisable)
|
||||||
|
docancel(self);
|
||||||
|
break;
|
||||||
|
case -1:
|
||||||
|
self->cancelpoint--;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
self->canceldisable += x;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* "rsyscall" is a mechanism by which a thread can synchronously force all
|
/* "rsyscall" is a mechanism by which a thread can synchronously force all
|
||||||
|
|
|
@ -3,8 +3,8 @@
|
||||||
int pthread_setcancelstate(int new, int *old)
|
int pthread_setcancelstate(int new, int *old)
|
||||||
{
|
{
|
||||||
struct pthread *self = pthread_self();
|
struct pthread *self = pthread_self();
|
||||||
if (old) *old = self->canceldisable;
|
if (old) *old = self->canceldisable & 1;
|
||||||
if ((unsigned)new > 1) return EINVAL;
|
if ((unsigned)new > 1) return EINVAL;
|
||||||
self->canceldisable = new;
|
self->canceldisable = (self->canceldisable & ~1) | new;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue