• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * File: exception1.c
3  *
4  *
5  * --------------------------------------------------------------------------
6  *
7  *      Pthreads-win32 - POSIX Threads Library for Win32
8  *      Copyright(C) 1998 John E. Bossom
9  *      Copyright(C) 1999,2005 Pthreads-win32 contributors
10  *
11  *      Contact Email: rpj@callisto.canberra.edu.au
12  *
13  *      The current list of contributors is contained
14  *      in the file CONTRIBUTORS included with the source
15  *      code distribution. The list can also be seen at the
16  *      following World Wide Web location:
17  *      http://sources.redhat.com/pthreads-win32/contributors.html
18  *
19  *      This library is free software; you can redistribute it and/or
20  *      modify it under the terms of the GNU Lesser General Public
21  *      License as published by the Free Software Foundation; either
22  *      version 2 of the License, or (at your option) any later version.
23  *
24  *      This library is distributed in the hope that it will be useful,
25  *      but WITHOUT ANY WARRANTY; without even the implied warranty of
26  *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
27  *      Lesser General Public License for more details.
28  *
29  *      You should have received a copy of the GNU Lesser General Public
30  *      License along with this library in the file COPYING.LIB;
31  *      if not, write to the Free Software Foundation, Inc.,
32  *      59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
33  *
34  * --------------------------------------------------------------------------
35  *
36  * Test Synopsis: Test passing of exceptions back to the application.
37  *
38  * Test Method (Validation or Falsification):
39  * -
40  *
41  * Requirements Tested:
42  * -
43  *
44  * Features Tested:
45  * -
46  *
47  * Cases Tested:
48  * -
49  *
50  * Description:
51  * -
52  *
53  * Environment:
54  * -
55  *
56  * Input:
57  * - None.
58  *
59  * Output:
60  * - File name, Line number, and failed expression on failure.
61  * - No output on success.
62  *
63  * Assumptions:
64  * - have working pthread_create, pthread_self, pthread_mutex_lock/unlock
65  *   pthread_testcancel, pthread_cancel, pthread_join
66  *
67  * Pass Criteria:
68  * - Process returns zero exit status.
69  *
70  * Fail Criteria:
71  * - Process returns non-zero exit status.
72  */
73 
74 #if defined(_MSC_VER) || defined(__cplusplus)
75 
76 #include "test.h"
77 
78 /*
79  * Create NUMTHREADS threads in addition to the Main thread.
80  */
81 enum {
82   NUMTHREADS = 4
83 };
84 
85 void *
exceptionedThread(void * arg)86 exceptionedThread(void * arg)
87 {
88   int dummy = 0;
89   intptr_t result = ((intptr_t)PTHREAD_CANCELED + 1);
90   /* Set to async cancelable */
91 
92   assert(pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL) == 0);
93 
94   assert(pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL) == 0);
95 
96   Sleep(100);
97 
98 #if defined(_MSC_VER) && !defined(__cplusplus)
99   __try
100   {
101     int zero = (int) arg; /* Passed in from arg to avoid compiler error */
102     int one = 1;
103     /*
104      * The deliberate exception condition (zero divide) is
105      * in an "if" to avoid being optimised out.
106      */
107     if (dummy == one/zero)
108       Sleep(0);
109   }
110   __except (EXCEPTION_EXECUTE_HANDLER)
111   {
112     /* Should get into here. */
113     result = ((int)PTHREAD_CANCELED + 2);
114   }
115 #elif defined(__cplusplus)
116   try
117   {
118     /*
119      * I had a zero divide exception here but it
120      * wasn't being caught by the catch(...)
121      * below under Mingw32. That could be a problem.
122      */
123     throw dummy;
124   }
125 #if defined(PtW32CatchAll)
126   PtW32CatchAll
127 #else
128   catch (...)
129 #endif
130   {
131     /* Should get into here. */
132     result = ((int)PTHREAD_CANCELED + 2);
133   }
134 #endif
135 
136   return (void *) result;
137 }
138 
139 void *
canceledThread(void * arg)140 canceledThread(void * arg)
141 {
142   intptr_t result = ((intptr_t)PTHREAD_CANCELED + 1);
143   int count;
144 
145   /* Set to async cancelable */
146 
147   assert(pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL) == 0);
148 
149   assert(pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL) == 0);
150 
151 #if defined(_MSC_VER) && !defined(__cplusplus)
152   __try
153   {
154     /*
155      * We wait up to 10 seconds, waking every 0.1 seconds,
156      * for a cancelation to be applied to us.
157      */
158     for (count = 0; count < 100; count++)
159       Sleep(100);
160   }
161   __except (EXCEPTION_EXECUTE_HANDLER)
162   {
163     /* Should NOT get into here. */
164     result = ((int)PTHREAD_CANCELED + 2);
165   }
166 #elif defined(__cplusplus)
167   try
168   {
169     /*
170      * We wait up to 10 seconds, waking every 0.1 seconds,
171      * for a cancelation to be applied to us.
172      */
173     for (count = 0; count < 100; count++)
174       Sleep(100);
175   }
176 #if defined(PtW32CatchAll)
177   PtW32CatchAll
178 #else
179   catch (...)
180 #endif
181   {
182     /* Should NOT get into here. */
183     result = ((int)PTHREAD_CANCELED + 2);
184   }
185 #endif
186 
187   return (void *) result;
188 }
189 
190 int
main()191 main()
192 {
193   int failed = 0;
194   int i;
195   pthread_t mt;
196   pthread_t et[NUMTHREADS];
197   pthread_t ct[NUMTHREADS];
198 
199   assert((mt = pthread_self()).p != NULL);
200 
201   for (i = 0; i < NUMTHREADS; i++)
202     {
203       assert(pthread_create(&et[i], NULL, exceptionedThread, (void *) 0) == 0);
204       assert(pthread_create(&ct[i], NULL, canceledThread, NULL) == 0);
205     }
206 
207   /*
208    * Code to control or munipulate child threads should probably go here.
209    */
210   Sleep(1000);
211 
212   for (i = 0; i < NUMTHREADS; i++)
213     {
214       assert(pthread_cancel(ct[i]) == 0);
215     }
216 
217   /*
218    * Give threads time to run.
219    */
220   Sleep(NUMTHREADS * 1000);
221 
222   /*
223    * Check any results here. Set "failed" and only print output on failure.
224    */
225   failed = 0;
226   for (i = 0; i < NUMTHREADS; i++)
227     {
228       int fail = 0;
229       intptr_t result = 0;
230 
231 	/* Canceled thread */
232       assert(pthread_join(ct[i], (void **) &result) == 0);
233       assert(!(fail = (result != (intptr_t) PTHREAD_CANCELED)));
234 
235       failed = (failed || fail);
236 
237       /* Exceptioned thread */
238       assert(pthread_join(et[i], (void **) &result) == 0);
239       assert(!(fail = (result != ((intptr_t) PTHREAD_CANCELED + 2))));
240 
241       failed = (failed || fail);
242     }
243 
244   assert(!failed);
245 
246   /*
247    * Success.
248    */
249   return 0;
250 }
251 
252 #else /* defined(_MSC_VER) || defined(__cplusplus) */
253 
254 #include <stdio.h>
255 
256 int
main()257 main()
258 {
259   fprintf(stderr, "Test N/A for this compiler environment.\n");
260   return 0;
261 }
262 
263 #endif /* defined(_MSC_VER) || defined(__cplusplus) */
264