1/*
2 * Copyright (c) 2002, Intel Corporation. All rights reserved.
3 * Created by:  rolla.n.selbak REMOVE-THIS AT intel 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 * void pthread_cleanup_push(void (*routine) (void*), void *arg);
9 *
10 * Shall push the specified cancelation cleanup handler routine onto the calling thread's
11 * cancelation cleanup stack. The cancelation cleanup handler shall be popped from the
12 * cancelation cleanup stack and invoked with the argument arg when:
13 *
14 * (a)- The thread exits (calls pthread_exit())
15 * (b)- The thread acts upon a cancelation request
16 * (c)- the thread calls pthread_cleanup_pop() with a non-zero execution argument
17 *
18 *  Testing (b)
19 *
20 * STEPS:
21 * 1. Create a thread
22 * 2. In the thread, push a cancelation handler
23 * 3. Main will cancel the thread before the thread exits
24 * 4. Verify that the cleanup handler was called
25 */
26
27#include <pthread.h>
28#include <stdio.h>
29#include <errno.h>
30#include <unistd.h>
31#include "posixtest.h"
32
33# define CLEANUP_NOTCALLED 0
34# define CLEANUP_CALLED 1
35
36# define INTHREAD 0 	/* Control going to or is already for Thread */
37# define INMAIN 1	/* Control going to or is already for Main */
38
39int sem1;		/* Manual semaphore */
40int cleanup_flag;
41
42/* The cleanup handler */
43void a_cleanup_func(void *flag_val)
44{
45	cleanup_flag = (long)flag_val;
46	sem1 = INMAIN;
47	return;
48}
49
50/* Function that the thread executes upon its creation */
51void *a_thread_func()
52{
53	pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
54	pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
55
56	pthread_cleanup_push(a_cleanup_func, (void*) CLEANUP_CALLED);
57
58	/* Indicate to main() that the thread has been created. */
59	sem1=INMAIN;
60
61	/* Wait until main() has sent out a cancel request, meaning until it
62	 * sets sem1==INTHREAD */
63	while(sem1==INMAIN)
64		sleep(1);
65
66	/* Give thread 10 seconds to time out.  If the cancel request was not
67	 * honored until now, the test is unresolved because the cancel request
68	 * was not handled correctly. */
69	sleep(10);
70
71	/* Shouldn't get here if the cancel request was honored immediately
72	 * like it should have been. */
73	pthread_cleanup_pop(0);
74	pthread_exit((void*)PTS_UNRESOLVED);
75	return NULL;
76}
77
78int main()
79{
80	pthread_t new_th;
81	void *value_ptr;		/* hold return value of thread from pthread_join */
82
83	/* Initializing values */
84	sem1=INTHREAD;
85	cleanup_flag=CLEANUP_NOTCALLED;
86
87	/* Create a new thread. */
88	if(pthread_create(&new_th, NULL, a_thread_func, NULL) != 0)
89	{
90		perror("Error creating thread\n");
91		return PTS_UNRESOLVED;
92	}
93
94	/* Make sure thread is created before we cancel it. (wait for
95	 * a_thread_func() to set sem1=1.) */
96	while(sem1==INTHREAD)
97		sleep(1);
98
99	if(pthread_cancel(new_th) != 0)
100	{
101		printf("Error: Couldn't cancel thread\n");
102		return PTS_UNRESOLVED;
103	}
104
105	/* Indicate to the thread function that the thread cancel request
106	 * has been sent to it. */
107	sem1=INTHREAD;
108
109	/* Wait for thread to return. */
110	if(pthread_join(new_th, &value_ptr) != 0)
111	{
112		printf("Error in pthread_join()\n");
113		return PTS_UNRESOLVED;
114	}
115
116	/* Make sure cancellation happened correctly */
117	if((long)value_ptr == PTS_UNRESOLVED)
118	{
119		printf("Error: cancellation not correctly handled\n");
120		return PTS_UNRESOLVED;
121	}
122
123	/* This means that the cleanup function wasn't called, so the cancel
124	 * request was not honord immediately like it should have been. */
125	if(cleanup_flag != CLEANUP_CALLED)
126	{
127		printf("Test FAILED: Cleanup hanlder not called up cancellation\n");
128		return PTS_FAIL;
129	}
130
131	printf("Test PASSED\n");
132	return PTS_PASS;
133}
134
135
136