1 | // Licensed to the .NET Foundation under one or more agreements. |
2 | // The .NET Foundation licenses this file to you under the MIT license. |
3 | // See the LICENSE file in the project root for more information. |
4 | |
5 | /*===================================================================== |
6 | ** |
7 | ** Source: CriticalSectionFunctions/test5/test5.c |
8 | ** |
9 | ** Purpose: Attempt to delete a critical section owned by another |
10 | ** thread. |
11 | ** |
12 | ** |
13 | **===================================================================*/ |
14 | #include <palsuite.h> |
15 | |
16 | /* |
17 | * Tokens 0 and 1 are events. Token 2 is the thread. |
18 | */ |
19 | #define NUM_TOKENS 3 |
20 | |
21 | HANDLE hToken[NUM_TOKENS]; |
22 | CRITICAL_SECTION CriticalSection; |
23 | |
24 | BOOL CleanupHelper (HANDLE *hArray, DWORD dwIndex) |
25 | { |
26 | BOOL bCHRet; |
27 | |
28 | bCHRet = CloseHandle(hArray[dwIndex]); |
29 | if (!bCHRet) |
30 | { |
31 | Trace("PALSUITE ERROR: Unable to execute CloseHandle(%p) during " |
32 | "clean up.\nGetLastError returned '%u'.\n" , hArray[dwIndex], |
33 | GetLastError()); |
34 | } |
35 | |
36 | return (bCHRet); |
37 | } |
38 | |
39 | BOOL Cleanup(HANDLE *hArray, DWORD dwIndex) |
40 | { |
41 | BOOL bCRet; |
42 | BOOL bCHRet = FALSE; |
43 | |
44 | while (--dwIndex > 0) |
45 | { |
46 | bCHRet = CleanupHelper(&hArray[0], dwIndex); |
47 | } |
48 | |
49 | bCRet = CloseHandle(hArray[0]); |
50 | if (!bCRet) |
51 | { |
52 | Trace("PALSUITE ERROR: Unable to execute CloseHandle(%p) during " |
53 | "clean up.\nGetLastError returned '%u'.\n" , hArray[dwIndex], |
54 | GetLastError()); |
55 | } |
56 | |
57 | return (bCRet&&bCHRet); |
58 | } |
59 | |
60 | DWORD PALAPI Thread(LPVOID lpParam) |
61 | { |
62 | DWORD dwTRet; |
63 | |
64 | EnterCriticalSection(&CriticalSection); |
65 | |
66 | /* signal thread 0 */ |
67 | if (0 == SetEvent(hToken[0])) |
68 | { |
69 | Trace("PALSUITE ERROR: Unable to execute SetEvent(%p) during " |
70 | "clean up.\nGetLastError returned '%u'.\n" , hToken[0], |
71 | GetLastError()); |
72 | LeaveCriticalSection(&CriticalSection); |
73 | Cleanup (&hToken[0], NUM_TOKENS); |
74 | DeleteCriticalSection(&CriticalSection); |
75 | Fail("" ); |
76 | } |
77 | |
78 | /* wait to be signaled */ |
79 | dwTRet = WaitForSingleObject(hToken[1], 10000); |
80 | if (WAIT_OBJECT_0 != dwTRet) |
81 | |
82 | { |
83 | Trace("PALSUITE ERROR: WaitForSingleObject(%p,%d) should have " |
84 | "returned\nWAIT_OBJECT_0 ('%d'), instead it returned " |
85 | "('%d').\nGetLastError returned '%u'.\n" , |
86 | hToken[1], 10000, WAIT_OBJECT_0, dwTRet, GetLastError()); |
87 | LeaveCriticalSection(&CriticalSection); |
88 | Cleanup (&hToken[0], NUM_TOKENS); |
89 | DeleteCriticalSection(&CriticalSection); |
90 | Fail("" ); |
91 | } |
92 | |
93 | LeaveCriticalSection(&CriticalSection); |
94 | return 0; |
95 | } |
96 | |
97 | int __cdecl main(int argc, char **argv) |
98 | { |
99 | DWORD dwThreadId; |
100 | DWORD dwMRet; |
101 | |
102 | if ((PAL_Initialize(argc,argv)) != 0) |
103 | { |
104 | return(FAIL); |
105 | } |
106 | |
107 | /* thread 0 event */ |
108 | hToken[0] = CreateEvent(NULL, TRUE, FALSE, NULL); |
109 | if (NULL == hToken[0]) |
110 | { |
111 | Fail("PALSUITE ERROR: CreateEvent call #0 failed. GetLastError " |
112 | "returned %u.\n" , GetLastError()); |
113 | } |
114 | |
115 | /* thread 1 event */ |
116 | hToken[1] = CreateEvent(NULL, TRUE, FALSE, NULL); |
117 | if (NULL == hToken[1]) |
118 | { |
119 | Trace("PALSUITE ERROR: CreateEvent call #1 failed. GetLastError " |
120 | "returned %u.\n" , GetLastError()); |
121 | Cleanup(&hToken[0], (NUM_TOKENS - 2)); |
122 | Fail("" ); |
123 | } |
124 | |
125 | InitializeCriticalSection(&CriticalSection); |
126 | |
127 | hToken[2] = CreateThread(NULL, |
128 | 0, |
129 | &Thread, |
130 | (LPVOID) NULL, |
131 | 0, |
132 | &dwThreadId); |
133 | if (hToken[2] == NULL) |
134 | { |
135 | Trace("PALSUITE ERROR: CreateThread call #0 failed. GetLastError " |
136 | "returned %u.\n" , GetLastError()); |
137 | Cleanup(&hToken[0], (NUM_TOKENS - 1)); |
138 | DeleteCriticalSection(&CriticalSection); |
139 | Fail("" ); |
140 | } |
141 | |
142 | /* wait for thread 0 to be signaled */ |
143 | dwMRet = WaitForSingleObject(hToken[0], 10000); |
144 | if (WAIT_OBJECT_0 != dwMRet) |
145 | { |
146 | Trace("PALSUITE ERROR: WaitForSingleObject(%p,%d) should have " |
147 | "returned\nWAIT_OBJECT_0 ('%d'), instead it returned " |
148 | "('%d').\nGetLastError returned '%u'.\n" , hToken[0], 10000, |
149 | WAIT_OBJECT_0, dwMRet, GetLastError()); |
150 | Cleanup(&hToken[0], NUM_TOKENS); |
151 | Fail("" ); |
152 | } |
153 | |
154 | /* |
155 | * Attempt to do delete CriticalSection object owned by other thread |
156 | */ |
157 | DeleteCriticalSection(&CriticalSection); |
158 | |
159 | /* signal thread 1 */ |
160 | if (0 == SetEvent(hToken[1])) |
161 | { |
162 | Trace("PALSUITE ERROR: Unable to execute SetEvent(%p) call.\n" |
163 | "GetLastError returned '%u'.\n" , hToken[1], |
164 | GetLastError()); |
165 | Cleanup(&hToken[0], NUM_TOKENS); |
166 | Fail("" ); |
167 | } |
168 | |
169 | dwMRet = WaitForSingleObject(hToken[2], 10000); |
170 | if (WAIT_OBJECT_0 != dwMRet) |
171 | { |
172 | Trace("PALSUITE ERROR: WaitForSingleObject(%p, %d) call " |
173 | "returned an unexpected value '%d'.\nGetLastError returned " |
174 | "%u.\n" , hToken[2], 10000, dwMRet, GetLastError()); |
175 | Cleanup(&hToken[0], NUM_TOKENS); |
176 | Fail("" ); |
177 | } |
178 | |
179 | if (!Cleanup(&hToken[0], NUM_TOKENS)) |
180 | { |
181 | Fail("" ); |
182 | } |
183 | |
184 | PAL_Terminate(); |
185 | |
186 | return (PASS); |
187 | } |
188 | |