* sysdeps/pthread/aio_notify.c (notify_func_wrapper): Take a malloc'd

struct containing function ptr and value, free it.
	(__aio_notify_only): Allocate that and copy values from SIGEV into it.
	It's not safe to let the new thread use the SIGEV pointer.
This commit is contained in:
Roland McGrath 2002-12-09 07:14:24 +00:00
parent 531da978ce
commit 57b4cb2522
2 changed files with 37 additions and 3 deletions

View File

@ -1,3 +1,10 @@
2002-12-08 Roland McGrath <roland@redhat.com>
* sysdeps/pthread/aio_notify.c (notify_func_wrapper): Take a malloc'd
struct containing function ptr and value, free it.
(__aio_notify_only): Allocate that and copy values from SIGEV into it.
It's not safe to let the new thread use the SIGEV pointer.
2001-10-20 Paul Eggert <eggert@twinsun.com>
* misc/error.c (strerror_r): Do not declare unless [!_LIBC].

View File

@ -25,11 +25,20 @@
#include "aio_misc.h"
struct notify_func
{
void (*func) (sigval_t);
sigval_t value;
};
static void *
notify_func_wrapper (void *arg)
{
struct sigevent *sigev = arg;
sigev->sigev_notify_function (sigev->sigev_value);
struct notify_func *const n = arg;
void (*func) (sigval_t) = n->func;
sigval_t value = n->value;
free (n);
(*func) (value);
return NULL;
}
@ -55,8 +64,26 @@ __aio_notify_only (struct sigevent *sigev, pid_t caller_pid)
pattr = &attr;
}
if (pthread_create (&tid, pattr, notify_func_wrapper, sigev) < 0)
/* SIGEV may be freed as soon as we return, so we cannot let the
notification thread use that pointer. Even though a sigval_t is
only one word and the same size as a void *, we cannot just pass
the value through pthread_create as the argument and have the new
thread run the user's function directly, because on some machines
the calling convention for a union like sigval_t is different from
that for a pointer type like void *. */
struct notify_func *nf = malloc (sizeof *nf);
if (nf == NULL)
result = -1;
else
{
nf->func = sigev->sigev_notify_function;
nf->value = sigev->sigev_value;
if (pthread_create (&tid, pattr, notify_func_wrapper, nf) < 0)
{
free (nf);
result = -1;
}
}
}
else if (sigev->sigev_notify == SIGEV_SIGNAL)
{