1/* 2 * Copyright (c) 2004, QUALCOMM Inc. All rights reserved. 3 * Created by: abisain REMOVE-THIS AT qualcomm DOT com 4 * This file is licensed under the GPL license. For the full content 5 * of this license, see the COPYING file at the top level of this 6 * source tree. 7 8 * Test pthread_cancel() 9 * 10 * Any destructors for thread_specific data will be called after 11 * all cleanup handlers return 12 * 13 * Steps: 14 * 1. Create a new thread. 15 * 2. Create a thread specific object in the thread with a destructor 16 * 3. Add a cleanup function in the thread 17 * 4. Call pthread_cancel on the thread. 18 * 5. Make sure that the destructor was called after the cleanup handler 19 * 20 */ 21 22#include <pthread.h> 23#include <stdio.h> 24#include <stdlib.h> 25#include <unistd.h> 26#include "posixtest.h" 27 28#define TEST "2-3" 29#define FUNCTION "pthread_cancel" 30#define ERROR_PREFIX "unexpected error: " FUNCTION " " TEST ": " 31 32int cleanup_flag = 0; 33int destructor_flag = 0; 34int sem = 0; /* manual semaphore */ 35struct timespec destructor_time, cleanup_time; 36 37/* 38 Destructor for the Thread Specific Data 39 */ 40void destructor(void *tmp) 41{ 42 clock_gettime(CLOCK_REALTIME, &destructor_time); 43 destructor_flag = 1; 44} 45 46/* 47 Cleanup Handler for the Thread 48 */ 49void cleanup_function() 50{ 51 clock_gettime(CLOCK_REALTIME, &cleanup_time); 52 cleanup_flag = 1; 53} 54 55/* Thread's function. */ 56void *a_thread_func(void *tmp) 57{ 58 pthread_key_t key; 59 int value = 1; 60 int rc = 0; 61 62 /* To enable thread immediate cancelation, since the default 63 * is PTHREAD_CANCEL_DEFERRED. */ 64 rc = pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); 65 if (rc != 0) { 66 printf(ERROR_PREFIX "pthread_setcanceltype\n"); 67 exit(PTS_UNRESOLVED); 68 } 69 70 rc = pthread_key_create(&key, destructor); 71 if (rc != 0) { 72 printf(ERROR_PREFIX "pthread_key_create\n"); 73 exit(PTS_UNRESOLVED); 74 } 75 76 rc = pthread_setspecific(key, &value); 77 if (rc != 0) { 78 printf(ERROR_PREFIX "pthread_setspecific\n"); 79 exit(PTS_UNRESOLVED); 80 } 81 82 pthread_cleanup_push(cleanup_function, NULL); 83 84 /* Tell main that the key is created */ 85 sem = 1; 86 87 /* Sleep forever */ 88 while(1) 89 sleep(5); 90 91 pthread_cleanup_pop(0); 92 return NULL; 93} 94 95int main() 96{ 97 pthread_t new_th; 98 int rc = 0; 99 double diff; 100 sem = 0; 101 102 /* Create a new thread. */ 103 rc = pthread_create(&new_th, NULL, a_thread_func, NULL); 104 if(rc != 0) { 105 printf(ERROR_PREFIX "pthread_create\n"); 106 exit(PTS_UNRESOLVED); 107 } 108 109 /* Wait for the thread to be ready */ 110 while(sem == 0) 111 sleep(1); 112 113 /* Cancel the thread. */ 114 rc = pthread_cancel(new_th); 115 if(rc != 0) { 116 printf(ERROR_PREFIX "pthread_cancel\n"); 117 exit(PTS_UNRESOLVED); 118 } 119 120 /* Delay enough so that the destructor must have been called */ 121 sleep(5); 122 123 if(cleanup_flag != 1) { 124 printf(ERROR_PREFIX "Test FAIL: Cleanup handler was not executed.\n"); 125 exit(PTS_FAIL); 126 } 127 128 if(destructor_flag != 1) { 129 printf(ERROR_PREFIX "Test FAIL: Destructor was not executed.\n"); 130 exit(PTS_FAIL); 131 } 132 133 diff = destructor_time.tv_sec - cleanup_time.tv_sec; 134 diff += (double)(destructor_time.tv_nsec - cleanup_time.tv_nsec)/1000000000.0; 135 if(diff < 0) { 136 printf(ERROR_PREFIX "Test FAIL: Destructor called before Cleanup Handler\n"); 137 exit(PTS_FAIL); 138 } 139 140 printf("Test PASS\n"); 141 exit(PTS_PASS); 142} 143 144 145