Current-Users archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

libpthread problem when using custom stack


devel/p5-Coro is a perl module providing threading support.

The current version 6.57 had lots of segfaults on NetBSD. I
investigated with help of the author Marc Lehmann.

We found that setting up the stack (i.e. the mmap()s) worked fine, but
then actually using the stack lead to random segfaults.

The code is quite straightforward (unifdef'ed for NetBSD), see below.

When used as shown below, the random segfaults happen. When the
(commented out) pthread_attr_setguardsize() is enabled, the segfaults

According to the NetBSD man page for pthread_attr_setguardsize(), the
effect of this function is ignored when pthread_attr_setstack() is
used. This does not seem to be the case here.

--- begin quote from pthread_attr_getguardsize(3) ---

If pthread_attr_setstack(3) or pthread_attr_setstackaddr(3) is used to
set the stack address attribute in attr, the guard size attribute is
ignored and no guard area will be allocated; it is the responsibility
of the application to handle the overflow conditions.

--- end quote ---

Last year's GSoC porting wine had a similar issue, see :

--- begin quote from blog entry ---

Eventually, I found that pthread_attr_setstack(3) was setting the
guard size to 65536 bytes even though the man page said otherwise. And
Wine relied on it not being set. This resulted in out-of-bound access
which caused the unhandled page fault. After setting the guard size to
0 using pthread_attr_setguardsize(3), Wine started behaving fine.

--- end quote ---

I think there is a bug in libpthread. Is this enough for a bug report
or what more information is needed? Or perhaps someone already knows
how to fix this?


From Coro-6.57/Coro/libcoro/coro.c:

coro_create (coro_context *ctx, coro_func coro, void *arg, void *sptr, size_t ssize)
  static coro_context nctx;
  static int once;

  if (!once)
      once = 1;

      pthread_cond_init (&, 0);

  pthread_cond_init (&ctx->cv, 0);

  if (coro)
      pthread_attr_t attr;
      struct coro_init_args args;
      pthread_t id;

      args.func = coro;
      args.arg  = arg;
      args.self = ctx;
      args.main = &nctx;

      pthread_attr_init (&attr);
      // pthread_attr_setguardsize (&attr, 0);
      pthread_attr_setstack (&attr, sptr, (size_t)ssize);
      pthread_attr_setscope (&attr, PTHREAD_SCOPE_PROCESS);
      pthread_create (&id, &attr, coro_init, &args);

      coro_transfer (args.main, args.self);

Home | Main Index | Thread Index | Old Index