1570af302Sopenharmony_ci// commit: fb11b6b85e1e01daf17228be32d7f98b47517363 2011-02-19 2570af302Sopenharmony_ci// pthread_exit should call dtors (even in the last thread) 3570af302Sopenharmony_ci#include <stdlib.h> 4570af302Sopenharmony_ci#include <string.h> 5570af302Sopenharmony_ci#include <errno.h> 6570af302Sopenharmony_ci#include <pthread.h> 7570af302Sopenharmony_ci#include <sys/wait.h> 8570af302Sopenharmony_ci#include <unistd.h> 9570af302Sopenharmony_ci#include "test.h" 10570af302Sopenharmony_ci 11570af302Sopenharmony_ci#define TEST(r, f) if (((r)=(f))) t_error(#f " failed: %s\n", strerror(r)) 12570af302Sopenharmony_ci#define TESTC(c, m) ( (c) || (t_error("%s failed (" m ")\n", #c), 0) ) 13570af302Sopenharmony_ci 14570af302Sopenharmony_cistatic pthread_key_t k; 15570af302Sopenharmony_cistatic int data; 16570af302Sopenharmony_ci 17570af302Sopenharmony_cistatic void dtor(void *p) 18570af302Sopenharmony_ci{ 19570af302Sopenharmony_ci *(int *)p = 1; 20570af302Sopenharmony_ci} 21570af302Sopenharmony_ci 22570af302Sopenharmony_cistatic void *start(void *arg) 23570af302Sopenharmony_ci{ 24570af302Sopenharmony_ci if (pthread_setspecific(k, arg)) 25570af302Sopenharmony_ci return arg; 26570af302Sopenharmony_ci return 0; 27570af302Sopenharmony_ci} 28570af302Sopenharmony_ci 29570af302Sopenharmony_cistatic void cleanup(void) 30570af302Sopenharmony_ci{ 31570af302Sopenharmony_ci TESTC(data == 1, "dtor was not run for the last thread"); 32570af302Sopenharmony_ci _exit(t_status); 33570af302Sopenharmony_ci} 34570af302Sopenharmony_ci 35570af302Sopenharmony_cistatic void die(void) 36570af302Sopenharmony_ci{ 37570af302Sopenharmony_ci _exit(1); 38570af302Sopenharmony_ci} 39570af302Sopenharmony_ci 40570af302Sopenharmony_ciint main(void) 41570af302Sopenharmony_ci{ 42570af302Sopenharmony_ci pthread_t td; 43570af302Sopenharmony_ci int r, arg=0, pid; 44570af302Sopenharmony_ci void *res; 45570af302Sopenharmony_ci 46570af302Sopenharmony_ci // test if atexit handlers are run after pthread_exit 47570af302Sopenharmony_ci // (early musl failed this test) 48570af302Sopenharmony_ci pid = fork(); 49570af302Sopenharmony_ci switch (pid) { 50570af302Sopenharmony_ci case -1: 51570af302Sopenharmony_ci t_error("fork failed: %s\n", strerror(errno)); 52570af302Sopenharmony_ci return 1; 53570af302Sopenharmony_ci case 0: 54570af302Sopenharmony_ci atexit(die); 55570af302Sopenharmony_ci pthread_exit(0); 56570af302Sopenharmony_ci default: 57570af302Sopenharmony_ci if (waitpid(pid, &r, 0) != pid) { 58570af302Sopenharmony_ci t_error("waitpid failed: %s\n", strerror(errno)); 59570af302Sopenharmony_ci return 1; 60570af302Sopenharmony_ci } 61570af302Sopenharmony_ci if (!WIFEXITED(r) || WEXITSTATUS(r) != 1) { 62570af302Sopenharmony_ci t_error("atexit handler was not run after last thread exited" 63570af302Sopenharmony_ci " (exited=%d, signal=%d, status=%d, want exit status=1)\n", 64570af302Sopenharmony_ci WIFEXITED(r), !WIFEXITED(r)&&WIFSIGNALED(r)?WTERMSIG(r):0, WIFEXITED(r)?WEXITSTATUS(r):0); 65570af302Sopenharmony_ci return 1; 66570af302Sopenharmony_ci } 67570af302Sopenharmony_ci } 68570af302Sopenharmony_ci 69570af302Sopenharmony_ci // dtor should set tsd (arg and data) from 0 to 1 70570af302Sopenharmony_ci if (atexit(cleanup)) { 71570af302Sopenharmony_ci t_error("atexit failed\n"); 72570af302Sopenharmony_ci return 1; 73570af302Sopenharmony_ci } 74570af302Sopenharmony_ci TEST(r, pthread_key_create(&k, dtor)); 75570af302Sopenharmony_ci TEST(r, pthread_setspecific(k, &data)); 76570af302Sopenharmony_ci TEST(r, pthread_create(&td, 0, start, &arg)); 77570af302Sopenharmony_ci TEST(r, pthread_join(td, &res)); 78570af302Sopenharmony_ci TESTC(res == 0, "pthread_setspecific failed in thread"); 79570af302Sopenharmony_ci TESTC(arg == 1, "dtor failed to run"); 80570af302Sopenharmony_ci TESTC(data == 0, "tsd in main thread is corrupted"); 81570af302Sopenharmony_ci TESTC(pthread_getspecific(k) == &data, "tsd in main thread is corrupted"); 82570af302Sopenharmony_ci pthread_exit(0); 83570af302Sopenharmony_ci} 84