This is the mail archive of the
libc-help@sourceware.org
mailing list for the glibc project.
segfault with pthread_cancel() and PTHREAD_STACK_MIN on armv7
- From: Michael Weiser <michael at weiser dot dinsnail dot net>
- To: libc-help at sourceware dot org
- Date: Fri, 10 Feb 2017 20:23:07 +0100
- Subject: segfault with pthread_cancel() and PTHREAD_STACK_MIN on armv7
- Authentication-results: sourceware.org; auth=none
Hi,
I run Gentoo Linux on Cubieboard2s (armv7v, le and be) with the
distribution's glibc-2.23. The whole system recompiled itself without
problems using gcc-6.3.0. This gcc is hardened, i.e. configured amongst
others with --enable-default-ssp.
Now I've run into a peculiar problem with pthreads, manifesting itself
in ntpd segfaulting upon startup. Turns out for very specific reasons
they spawn a thread doing an endless loop of sleep(10)'s and cancel
that. Also, they set the thread's stack size to PTHREAD_STACK_MIN.
(rationale and code can be seen here:
https://github.com/ntp-project/ntp/blob/stable/ntpd/ntpd.c#L252)
After isolating the code into the attached testcase I found that
increasing the thread's stack size by 6640 bytes or eliminating
pthread_cancel() altogehter both make the segfault go away.
The same testcase runs fine on an otherwise identical x86_64 install of
Gentoo compiled with the same kind of hardened gcc-6.3.0.
So I guess my question is: Is pthread_cancel() supposed to work with a
stack size of PTHREAD_STACK_MIN on every platform?
What might be causing my platform to require 6640 bytes more stack to
succeed?
--
Thanks,
Michael
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <errno.h>
#include <string.h>
#define PTHREAD_STACK_MIN 16384
/* segfaults: #define PT_STACK_EXTRA (6639) */
#define PT_STACK_EXTRA (6640) /* works */
static void* my_pthread_warmup_worker(void *thread_args) {
(void)thread_args;
for (;;)
sleep(10);
return NULL;
}
static void my_pthread_warmup(void) {
pthread_t thread;
pthread_attr_t thr_attr;
int rc;
pthread_attr_init(&thr_attr);
rc = pthread_attr_setstacksize(&thr_attr, PTHREAD_STACK_MIN + PT_STACK_EXTRA);
if (0 != rc)
printf("my_pthread_warmup: pthread_attr_setstacksize() -> %s",
strerror(rc));
rc = pthread_create(
&thread, &thr_attr, my_pthread_warmup_worker, NULL);
pthread_attr_destroy(&thr_attr);
if (0 != rc) {
printf("my_pthread_warmup: pthread_create() -> %s",
strerror(rc));
} else {
pthread_cancel(thread);
pthread_join(thread, NULL);
}
}
int main(void) {
my_pthread_warmup();
return 0;
}