This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
[PATCH] Memory fencing problem in pthread cancellation
- From: Jeff Law <law at redhat dot com>
- To: libc-alpha <libc-alpha at sourceware dot org>
- Date: Mon, 14 Jan 2013 13:27:02 -0700
- Subject: [PATCH] Memory fencing problem in pthread cancellation
Forgot the testcase. Run as a normal user.
#include <sys/wait.h>
#include <stdio.h>
#include <signal.h>
#include <pthread.h>
#include <errno.h>
#include <stdlib.h>
// gcc -g3 -O0 gcc_assert_dw2.c -lpthread
// http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52839#c10
void *foo(void *arg)
{
pthread_detach(pthread_self());
return NULL;
}
int create_foo_will_fail_with_eperm()
{
int ret;
int old;
pthread_t t;
struct sched_param sp;
pthread_attr_t ta;
ret = pthread_attr_init(&ta);
if (ret != 0) {
printf("attr init: %d %d\n", ret, errno);
exit(1);
}
ret = pthread_attr_setinheritsched(&ta, PTHREAD_EXPLICIT_SCHED);
if (ret != 0) {
printf("attr setinheritsched: %d %d\n", ret, errno);
exit(1);
}
ret = pthread_attr_setschedpolicy(&ta, SCHED_RR);
if (ret != 0) {
printf("attr setschedpolicy: %d %d\n", ret, errno);
exit(1);
}
sp.sched_priority = sched_get_priority_max(SCHED_RR);
ret = pthread_attr_setschedparam(&ta, &sp);
if (ret != 0) {
printf("attr setschedparam: %d %d\n", ret, errno);
exit(1);
}
ret = pthread_create(&t, &ta, foo, NULL);
if (ret == EPERM) {
/*
this is expected
printf("create foo: %d %d\n", ret, errno);
*/
} else {
printf("create foo suceeded: %d %d\n", ret, errno);
exit(2);
}
return 0;
}
int create_foo_thread()
{
int ret;
pthread_t t;
ret = pthread_create(&t, NULL, foo, NULL);
if (ret != 0) {
printf("create foo2: %d %d\n", ret, errno);
exit(3);
}
}
void *bar(void *arg)
{
int i;
int max1 = rand() % 8;
int max2 = rand() % 8;
int max3 = rand() % 8;
for (i=0; i < max1; i++)
create_foo_thread();
for (i=0; i < max2; i++)
create_foo_will_fail_with_eperm();
for (i=0; i < max3; i++)
create_foo_thread();
}
int do_child()
{
int ret;
pthread_t t;
ret = pthread_create(&t, NULL, bar, NULL);
if (ret != 0) {
printf("create bar: %d %d\n", ret, errno);
exit(4);
}
ret = pthread_join(t, NULL);
if (ret != 0) {
printf("join bar: %d\n", ret, errno);
exit(4);
}
}
int main()
{
int child;
int ret;
int status;
int i = 0;
srand(0);
while (1) {
i++;
if (i % 1000 == 0)
printf("%d\n", i);
child = fork();
if (child == 0) {
do_child();
pthread_exit(0);
printf("should not be reached\n");
exit(2);
}
ret = waitpid(child, &status, 0);
if (ret != child) {
printf("Waitpid returned the wrong PID");
exit(5);
}
if (!WIFEXITED(status)) {
printf("status: %d\n", status);
exit(6);
}
if (WEXITSTATUS(status) != 0) {
printf("exit status: %d\n", WEXITSTATUS(status));
exit(7);
}
}
return 0;
}