Add DRD suppression patterns for races triggered by std::ostream
[valgrind.git] / helgrind / tests / tc20_verifywrap.c
blobc110000791a2da28c65d215108be7e73bcd7d7f6
1 /* This program attempts to verify that all functions that are
2 supposed to be wrapped by tc_intercepts.c really are wrapped. The
3 main way it does this is to cause failures in those functions, so
4 as to obtain various error messages which imply that the wrapper
5 really did engage.
7 Any regressions shown up by this program are potentially serious
8 and should be investigated carefully. */
10 /* Needed for older glibcs (2.3 and older, at least) who don't
11 otherwise "know" about some more exotic pthread stuff, in this case
12 PTHREAD_MUTEX_ERRORCHECK. */
13 #define _GNU_SOURCE 1
14 #include <stdio.h>
15 #include <string.h>
16 #include <assert.h>
17 #include <unistd.h>
18 #include "safe-pthread.h"
19 #include "safe-semaphore.h"
21 #if !defined(__APPLE__)
23 #if defined(__sun__)
24 /* Fake __GLIBC_PREREQ on Solaris. Pretend glibc >= 2.4. */
25 # define __GLIBC_PREREQ
26 #else
27 #if !defined(__GLIBC_PREREQ)
28 # error "This program needs __GLIBC_PREREQ (in /usr/include/features.h)"
29 #endif
30 #endif /* __sun__ */
32 typedef union {
33 pthread_spinlock_t spinlock;
34 pthread_rwlock_t rwlock;
35 } spin_rw_lock;
37 short unprotected = 0;
39 void* lazy_child ( void* v ) {
40 assert(0); /* does not run */
43 void* racy_child ( void* v ) {
44 unprotected = 1234;
45 return NULL;
48 int main ( void )
50 int r;
51 /* pthread_t thr; */
52 /* pthread_attr_t thra; */
53 pthread_mutexattr_t mxa, mxa2;
54 pthread_mutex_t mx, mx2, mx3, mx4;
55 pthread_cond_t cv;
56 struct timespec abstime;
57 pthread_rwlock_t rwl;
58 pthread_rwlock_t rwl2;
59 pthread_rwlock_t rwl3;
60 sem_t s1;
62 # if __GLIBC_PREREQ(2,4)
63 fprintf(stderr,
64 "\n\n------ This is output for >= glibc 2.4 ------\n");
65 # else
66 fprintf(stderr,
67 "\n\n------ This is output for < glibc 2.4 ------\n");
68 # endif
70 /* --------- pthread_create/join --------- */
72 fprintf(stderr,
73 "\n---------------- pthread_create/join ----------------\n\n");
75 /* make pthread_create fail */
76 /* It's amazingly difficult to make pthread_create fail
77 without first soaking up all the machine's resources.
78 Instead, in order to demonstrate that it's really wrapped,
79 create a child thread, generate a race error, and join with it
80 again. */
81 /* This just segfaults:
82 memset( &thra, 0xFF, sizeof(thra) );
83 r= pthread_create( &thr, NULL, lazy_child, NULL ); assert(r);
85 { pthread_t child;
86 r= pthread_create( &child, NULL, racy_child, NULL ); assert(!r);
87 sleep(1); /* just to ensure parent thread reports race, not child */
88 unprotected = 5678;
89 r= pthread_join( child, NULL ); assert(!r);
92 /* make pthread_join fail */
93 r= pthread_join( pthread_self(), NULL ); assert(r);
95 /* --------- pthread_mutex_lock et al --------- */
97 fprintf(stderr,
98 "\n---------------- pthread_mutex_lock et al ----------------\n\n");
100 /* make pthread_mutex_init fail */
101 #if defined(__sun__)
102 pthread_mutexattr_init( &mxa );
103 memset( mxa.__pthread_mutexattrp, 0xFF, 5 * sizeof(int) );
104 #else
105 memset( &mxa, 0xFF, sizeof(mxa) );
106 #endif
107 r= pthread_mutex_init( &mx, &mxa );
108 # if __GLIBC_PREREQ(2,4)
109 assert(r); /* glibc >= 2.4: the call should fail */
110 # else
111 assert(!r); /* glibc < 2.4: oh well, glibc didn't bounce this */
112 # endif
114 /* make pthread_mutex_destroy fail */
115 r= pthread_mutex_init( &mx2, NULL ); assert(!r);
116 r= pthread_mutex_lock( &mx2 ); assert(!r);
117 r= pthread_mutex_destroy( &mx2 );
119 /* make pthread_mutex_lock fail (skipped on < glibc 2.4 because it
120 doesn't fail, hence hangs the test) */
121 # if __GLIBC_PREREQ(2,4)
122 memset( &mx3, 0xFF, sizeof(mx3) );
123 r= pthread_mutex_lock( &mx3 ); assert(r);
124 # else
125 fprintf(stderr, "\nmake pthread_mutex_lock fail: "
126 "skipped on glibc < 2.4\n\n");
127 # endif
129 /* make pthread_mutex_trylock fail */
130 memset( &mx3, 0xFF, sizeof(mx3) );
131 r= pthread_mutex_trylock( &mx3 ); assert(r);
133 /* make pthread_mutex_timedlock fail */
134 memset( &abstime, 0, sizeof(abstime) );
135 memset( &mx3, 0xFF, sizeof(mx3) );
136 r= pthread_mutex_timedlock( &mx3, &abstime ); assert(r);
138 /* make pthread_mutex_unlock fail */
139 memset( &mx3, 0xFF, sizeof(mx3) );
140 r= pthread_mutex_unlock( &mx3 );
141 # if __GLIBC_PREREQ(2,4)
142 assert(r);
143 # else
144 assert(!r);
145 # endif
147 /* --------- pthread_cond_wait et al --------- */
149 fprintf(stderr,
150 "\n---------------- pthread_cond_wait et al ----------------\n\n");
152 /* make pthread_cond_wait fail. This is difficult. Our cunning
153 plan (tm) is to show up at pthread_cond_wait bearing a
154 not-locked mutex of the ERRORCHECK flavour and hope (as is
155 indeed the case with glibc-2.5) that pthread_cond_wait notices
156 it is not locked, and bounces our request. */
157 r= pthread_mutexattr_init( &mxa2 ); assert(!r);
158 r= pthread_mutexattr_settype( &mxa2, PTHREAD_MUTEX_ERRORCHECK );
159 assert(!r);
160 r= pthread_mutex_init( &mx4, &mxa2 ); assert(!r);
161 r= pthread_cond_init( &cv, NULL ); assert(!r);
162 r= pthread_cond_wait( &cv, &mx4 ); assert(r);
163 r= pthread_mutexattr_destroy( &mxa2 ); assert(!r);
165 /* make pthread_cond_signal fail. FIXME: can't figure out how
166 to */
167 r= pthread_cond_signal( &cv ); assert(!r);
168 fprintf(stderr, "\nFIXME: can't figure out how to "
169 "verify wrap of pthread_cond_signal\n\n");
171 /* make pthread_cond_broadcast fail. FIXME: can't figure out how
172 to */
173 r= pthread_cond_broadcast( &cv ); assert(!r);
174 fprintf(stderr, "\nFIXME: can't figure out how to "
175 "verify wrap of pthread_broadcast_signal\n\n");
177 /* make pthread_cond_timedwait fail. */
178 memset( &abstime, 0, sizeof(abstime) );
179 abstime.tv_nsec = 1000000000 + 1;
180 r= pthread_cond_timedwait( &cv, &mx4, &abstime ); assert(r);
182 /* --------- pthread_rwlock_* --------- */
184 fprintf(stderr,
185 "\n---------------- pthread_rwlock_* ----------------\n\n");
187 /* pthread_rwlock_init, pthread_rwlock_unlock */
188 /* pthread_rwlock_init: can't make glibc's implementation fail.
189 However, can demonstrate interceptedness by initialising but not
190 locking a lock and then unlocking it. Then the unlock call
191 should say "first seen at .. the init call." So this tests
192 wrappedness of both calls. */
193 r= pthread_rwlock_init( &rwl, NULL ); assert(!r);
194 r= pthread_rwlock_unlock( &rwl );
195 /* assert(r); *//* glibc doesn't complain. It really ought to. Oh well. */
197 /* We can infer the presence of wrapping for pthread_rwlock_rdlock,
198 pthread_rwlock_wrlock and pthread_rwlock_unlock by making
199 Thrcheck count the lockedness state, and warning when we unlock
200 a not-locked lock. Thusly: */
201 r= pthread_rwlock_init( &rwl2, NULL ); assert(!r);
203 /* w-lock it */
204 fprintf(stderr, "(1) no error on next line\n");
205 r= pthread_rwlock_wrlock( &rwl2 ); assert(!r);
206 /* unlock it */
207 fprintf(stderr, "(2) no error on next line\n");
208 r= pthread_rwlock_unlock( &rwl2 ); assert(!r);
209 /* unlock it again, get an error */
210 fprintf(stderr, "(3) ERROR on next line\n");
211 r= pthread_rwlock_unlock( &rwl2 );
212 #if defined(__sun__)
213 assert(r);
214 #else
215 assert(!r);
216 #endif
218 /* same game with r-locks */
219 r= pthread_rwlock_init( &rwl2, NULL ); assert(!r);
220 /* r-lock it twice */
221 fprintf(stderr, "(4) no error on next line\n");
222 r= pthread_rwlock_rdlock( &rwl2 ); assert(!r);
223 fprintf(stderr, "(5) no error on next line\n");
224 r= pthread_rwlock_rdlock( &rwl2 ); assert(!r);
225 /* unlock it twice */
226 fprintf(stderr, "(6) no error on next line\n");
227 r= pthread_rwlock_unlock( &rwl2 ); assert(!r);
228 fprintf(stderr, "(7) no error on next line\n");
229 r= pthread_rwlock_unlock( &rwl2 ); assert(!r);
230 /* unlock it again, get an error */
231 fprintf(stderr, "(8) ERROR on next line\n");
232 r= pthread_rwlock_unlock( &rwl2 );
233 #if defined(__sun__)
234 assert(r);
235 #else
236 assert(!r);
237 #endif
239 /* Lock rwl3 so the locked-lock-at-dealloc check can complain about
240 it. */
241 r= pthread_rwlock_init( &rwl3, NULL ); assert(!r);
242 r= pthread_rwlock_rdlock( &rwl3 ); assert(!r);
244 /* --------- pthread_spin_* --------- */
246 fprintf(stderr,
247 "\n---------------- pthread_spin_* ----------------\n\n");
249 /* The following sequence verifies correct wrapping of pthread_spin_init()
250 and pthread_spin_destroy(). */
251 spin_rw_lock srwl1;
252 pthread_spin_init(&srwl1.spinlock, PTHREAD_PROCESS_PRIVATE);
253 pthread_spin_destroy(&srwl1.spinlock);
255 pthread_rwlock_init(&srwl1.rwlock, NULL);
256 pthread_rwlock_destroy(&srwl1.rwlock);
258 /* ------------- sem_* ------------- */
260 /* This is pretty lame, and duplicates tc18_semabuse.c. */
262 fprintf(stderr,
263 "\n---------------- sem_* ----------------\n\n");
265 /* verifies wrap of sem_init */
266 /* Do sem_init with huge initial count - fails */
267 r= sem_init(&s1, 0, ~0); assert(r);
269 /* initialise properly */
270 r= sem_init(&s1, 0, 0);
272 /* in glibc, sem_destroy is a no-op; making it fail is
273 impossible. */
274 fprintf(stderr, "\nFIXME: can't figure out how to verify wrap of "
275 "sem_destroy\n\n");
277 /* verifies wrap of sem_wait */
278 /* Do 'wait' on a bogus semaphore. This should fail, but on glibc
279 it succeeds. */
280 memset(&s1, 0x55, sizeof(s1));
281 r= sem_wait(&s1); /* assert(r != 0); */
283 /* this only fails with glibc 2.7 or later. */
284 r= sem_post(&s1);
285 fprintf(stderr, "\nFIXME: can't figure out how to verify wrap of "
286 "sem_post\n\n");
288 sem_destroy(&s1);
290 /* ------------- dealloc of mem holding locks ------------- */
292 fprintf(stderr,
293 "\n------------ dealloc of mem holding locks ------------\n\n");
295 /* At this point it should complain about deallocation
296 of memory containing locked locks:
297 rwl3
300 return 0;
303 #else /* defined(__APPLE__) */
304 int main ( void )
306 fprintf(stderr, "This program does not work on Mac OS X.\n");
307 return 0;
309 #endif