Blame src/regression/pthread_exit-dtor.c

Szabolcs Nagy cfa23c
// commit: fb11b6b85e1e01daf17228be32d7f98b47517363 2011-02-19
Szabolcs Nagy cfa23c
// pthread_exit should call dtors (even in the last thread)
Szabolcs Nagy cfa23c
#include <stdlib.h>
Szabolcs Nagy cfa23c
#include <string.h>
Szabolcs Nagy cfa23c
#include <errno.h>
Szabolcs Nagy cfa23c
#include <pthread.h>
Szabolcs Nagy cfa23c
#include <sys/wait.h>
Szabolcs Nagy cfa23c
#include <unistd.h>
Szabolcs Nagy cfa23c
#include "test.h"
Szabolcs Nagy cfa23c
Szabolcs Nagy cfa23c
#define TEST(r, f) if (((r)=(f))) t_error(#f " failed: %s\n", strerror(r))
Szabolcs Nagy cfa23c
#define TESTC(c, m) ( (c) || (t_error("%s failed (" m ")\n", #c), 0) )
Szabolcs Nagy cfa23c
Szabolcs Nagy cfa23c
static pthread_key_t k;
Szabolcs Nagy cfa23c
static int data;
Szabolcs Nagy cfa23c
Szabolcs Nagy cfa23c
static void dtor(void *p)
Szabolcs Nagy cfa23c
{
Szabolcs Nagy cfa23c
	*(int *)p = 1;
Szabolcs Nagy cfa23c
}
Szabolcs Nagy cfa23c
Szabolcs Nagy cfa23c
static void *start(void *arg)
Szabolcs Nagy cfa23c
{
Szabolcs Nagy cfa23c
	if (pthread_setspecific(k, arg))
Szabolcs Nagy cfa23c
		return arg;
Szabolcs Nagy cfa23c
	return 0;
Szabolcs Nagy cfa23c
}
Szabolcs Nagy cfa23c
Szabolcs Nagy cfa23c
static void cleanup(void)
Szabolcs Nagy cfa23c
{
Szabolcs Nagy cfa23c
	TESTC(data == 1, "dtor was not run for the last thread");
Szabolcs Nagy cfa23c
	_exit(t_status);
Szabolcs Nagy cfa23c
}
Szabolcs Nagy cfa23c
Szabolcs Nagy cfa23c
static void die(void)
Szabolcs Nagy cfa23c
{
Szabolcs Nagy cfa23c
	_exit(1);
Szabolcs Nagy cfa23c
}
Szabolcs Nagy cfa23c
Szabolcs Nagy cfa23c
int main(void)
Szabolcs Nagy cfa23c
{
Szabolcs Nagy cfa23c
	pthread_t td;
Szabolcs Nagy cfa23c
	int r, arg=0, pid;
Szabolcs Nagy cfa23c
	void *res;
Szabolcs Nagy cfa23c
Szabolcs Nagy cfa23c
	// test if atexit handlers are run after pthread_exit
Szabolcs Nagy cfa23c
	// (early musl failed this test)
Szabolcs Nagy cfa23c
	pid = fork();
Szabolcs Nagy cfa23c
	switch (pid) {
Szabolcs Nagy cfa23c
	case -1:
Szabolcs Nagy cfa23c
		t_error("fork failed: %s\n", strerror(errno));
Szabolcs Nagy cfa23c
		return 1;
Szabolcs Nagy cfa23c
	case 0:
Szabolcs Nagy cfa23c
		atexit(die);
Szabolcs Nagy cfa23c
		pthread_exit(0);
Szabolcs Nagy cfa23c
	default:
Szabolcs Nagy cfa23c
		if (waitpid(pid, &r, 0) != pid) {
Szabolcs Nagy cfa23c
			t_error("waitpid failed: %s\n", strerror(errno));
Szabolcs Nagy cfa23c
			return 1;
Szabolcs Nagy cfa23c
		}
Szabolcs Nagy cfa23c
		if (!WIFEXITED(r) || WEXITSTATUS(r) != 1) {
Szabolcs Nagy cfa23c
			t_error("atexit handler was not run after last thread exited"
Szabolcs Nagy cfa23c
				" (exited=%d, signal=%d, status=%d, want exit status=1)\n",
Szabolcs Nagy cfa23c
				WIFEXITED(r), !WIFEXITED(r)&&WIFSIGNALED(r)?WTERMSIG(r):0, WIFEXITED(r)?WEXITSTATUS(r):0);
Szabolcs Nagy cfa23c
			return 1;
Szabolcs Nagy cfa23c
		}
Szabolcs Nagy cfa23c
	}
Szabolcs Nagy cfa23c
Szabolcs Nagy cfa23c
	// dtor should set tsd (arg and data) from 0 to 1
Szabolcs Nagy cfa23c
	if (atexit(cleanup)) {
Szabolcs Nagy cfa23c
		t_error("atexit failed\n");
Szabolcs Nagy cfa23c
		return 1;
Szabolcs Nagy cfa23c
	}
Szabolcs Nagy cfa23c
	TEST(r, pthread_key_create(&k, dtor));
Szabolcs Nagy cfa23c
	TEST(r, pthread_setspecific(k, &data));
Szabolcs Nagy cfa23c
	TEST(r, pthread_create(&td, 0, start, &arg));
Szabolcs Nagy cfa23c
	TEST(r, pthread_join(td, &res));
Szabolcs Nagy cfa23c
	TESTC(res == 0, "pthread_setspecific failed in thread");
Szabolcs Nagy cfa23c
	TESTC(arg == 1, "dtor failed to run");
Szabolcs Nagy cfa23c
	TESTC(data == 0, "tsd in main thread is corrupted");
Szabolcs Nagy cfa23c
	TESTC(pthread_getspecific(k) == &data, "tsd in main thread is corrupted");
Szabolcs Nagy cfa23c
	pthread_exit(0);
Szabolcs Nagy cfa23c
}