From: Mark Wielaard Date: Mon, 19 Sep 2016 14:16:35 +0000 (+0000) Subject: Workaround bar_bad testcase hanging with newer glibc in helgrind/drd tests. X-Git-Tag: svn/VALGRIND_3_12_0~61 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=5f37e4dcde228872180c0cf28e6bee162fb3db08;p=thirdparty%2Fvalgrind.git Workaround bar_bad testcase hanging with newer glibc in helgrind/drd tests. This is a workaround for bug #358213 helgrind/drd pthread_barrier tests hangs with new glibc pthread barrier implementation. This makes sure that the tests don't hang anymore. It does this by creating new threads that sleep and kill the other threads after some time. But this introduces some non-determinism that might cause the tests to occassionally fail (both against old and new glibc implementations). git-svn-id: svn://svn.valgrind.org/valgrind/trunk@15962 --- diff --git a/drd/tests/Makefile.am b/drd/tests/Makefile.am index 2885391638..cfd74d04c8 100644 --- a/drd/tests/Makefile.am +++ b/drd/tests/Makefile.am @@ -81,8 +81,10 @@ EXTRA_DIST = \ atomic_var.stderr.exp \ atomic_var.vgtest \ bar_bad.stderr.exp \ + bar_bad.stderr.exp-nohang \ bar_bad.vgtest \ bar_bad_xml.stderr.exp \ + bar_bad_xml.stderr.exp-nohang \ bar_bad_xml.vgtest \ bar_trivial.stderr.exp \ bar_trivial.stdout.exp \ diff --git a/drd/tests/bar_bad.stderr.exp b/drd/tests/bar_bad.stderr.exp index 75f121f146..3581b085dd 100644 --- a/drd/tests/bar_bad.stderr.exp +++ b/drd/tests/bar_bad.stderr.exp @@ -34,16 +34,5 @@ barrier 0x........ was first observed at: destroy a barrier that was never initialised -Not a barrier - at 0x........: pthread_barrier_destroy (drd_pthread_intercepts.c:?) - by 0x........: main (bar_bad.c:?) - -Destruction of barrier that is being waited upon: barrier 0x........ - at 0x........: free (vg_replace_malloc.c:...) - by 0x........: main (bar_bad.c:?) -barrier 0x........ was first observed at: - at 0x........: pthread_barrier_init (drd_pthread_intercepts.c:?) - by 0x........: main (bar_bad.c:?) - -ERROR SUMMARY: 7 errors from 6 contexts (suppressed: 0 from 0) +ERROR SUMMARY: 5 errors from 4 contexts (suppressed: 0 from 0) diff --git a/drd/tests/bar_bad.stderr.exp-nohang b/drd/tests/bar_bad.stderr.exp-nohang new file mode 100644 index 0000000000..44f9651b4b --- /dev/null +++ b/drd/tests/bar_bad.stderr.exp-nohang @@ -0,0 +1,42 @@ + + +initialise a barrier with zero count +pthread_barrier_init: 'count' argument is zero: barrier 0x........ + at 0x........: pthread_barrier_init (drd_pthread_intercepts.c:?) + by 0x........: main (bar_bad.c:?) + + +initialise a barrier twice +Barrier reinitialization: barrier 0x........ + at 0x........: pthread_barrier_init (drd_pthread_intercepts.c:?) + by 0x........: main (bar_bad.c:?) +barrier 0x........ was first observed at: + at 0x........: pthread_barrier_init (drd_pthread_intercepts.c:?) + by 0x........: main (bar_bad.c:?) + + +initialise a barrier which has threads waiting on it +Barrier reinitialization: barrier 0x........ + at 0x........: pthread_barrier_init (drd_pthread_intercepts.c:?) + by 0x........: main (bar_bad.c:?) +barrier 0x........ was first observed at: + at 0x........: pthread_barrier_init (drd_pthread_intercepts.c:?) + by 0x........: main (bar_bad.c:?) + + +destroy a barrier that has waiting threads +Destruction of a barrier with active waiters: barrier 0x........ + at 0x........: pthread_barrier_destroy (drd_pthread_intercepts.c:?) + by 0x........: main (bar_bad.c:?) +barrier 0x........ was first observed at: + at 0x........: pthread_barrier_init (drd_pthread_intercepts.c:?) + by 0x........: main (bar_bad.c:?) + + +destroy a barrier that was never initialised +Not a barrier + at 0x........: pthread_barrier_destroy (drd_pthread_intercepts.c:?) + by 0x........: main (bar_bad.c:?) + + +ERROR SUMMARY: 6 errors from 5 contexts (suppressed: 0 from 0) diff --git a/drd/tests/bar_bad_xml.stderr.exp b/drd/tests/bar_bad_xml.stderr.exp index acb965656e..8539f75c77 100644 --- a/drd/tests/bar_bad_xml.stderr.exp +++ b/drd/tests/bar_bad_xml.stderr.exp @@ -204,78 +204,6 @@ destroy a barrier that has waiting threads destroy a barrier that was never initialised - - 0x........ - ... - GenericErr - Not a barrier - - - 0x........ - ... - pthread_barrier_destroy - ... - drd_pthread_intercepts.c - ... - - - 0x........ - ... - main - ... - bar_bad.c - ... - - - - - - 0x........ - ... - BarrierErr - Destruction of barrier that is being waited upon: barrier 0x........ - - - 0x........ - ... - free - ... - vg_replace_malloc.c - ... - - - 0x........ - ... - main - ... - bar_bad.c - ... - - - - barrier -
0x........
- - - 0x........ - ... - pthread_barrier_init - ... - drd_pthread_intercepts.c - ... - - - 0x........ - ... - main - ... - bar_bad.c - ... - - -
-
- FINISHED @@ -299,14 +227,6 @@ destroy a barrier that was never initialised ... 0x........ - - ... - 0x........ - - - ... - 0x........ - ... diff --git a/drd/tests/bar_bad_xml.stderr.exp-nohang b/drd/tests/bar_bad_xml.stderr.exp-nohang new file mode 100644 index 0000000000..a47cd603b7 --- /dev/null +++ b/drd/tests/bar_bad_xml.stderr.exp-nohang @@ -0,0 +1,264 @@ + + + + +4 +drd + + + ... + ... + ... + ... + + +... +... +drd + + + ... + + ./../../helgrind/tests/bar_bad + + + + + RUNNING + + + + +initialise a barrier with zero count + + 0x........ + ... + BarrierErr + pthread_barrier_init: 'count' argument is zero: barrier 0x........ + + + 0x........ + ... + pthread_barrier_init + ... + drd_pthread_intercepts.c + ... + + + 0x........ + ... + main + ... + bar_bad.c + ... + + + + + +initialise a barrier twice + + 0x........ + ... + BarrierErr + Barrier reinitialization: barrier 0x........ + + + 0x........ + ... + pthread_barrier_init + ... + drd_pthread_intercepts.c + ... + + + 0x........ + ... + main + ... + bar_bad.c + ... + + + + barrier +
0x........
+ + + 0x........ + ... + pthread_barrier_init + ... + drd_pthread_intercepts.c + ... + + + 0x........ + ... + main + ... + bar_bad.c + ... + + +
+
+ + +initialise a barrier which has threads waiting on it + + 0x........ + ... + BarrierErr + Barrier reinitialization: barrier 0x........ + + + 0x........ + ... + pthread_barrier_init + ... + drd_pthread_intercepts.c + ... + + + 0x........ + ... + main + ... + bar_bad.c + ... + + + + barrier +
0x........
+ + + 0x........ + ... + pthread_barrier_init + ... + drd_pthread_intercepts.c + ... + + + 0x........ + ... + main + ... + bar_bad.c + ... + + +
+
+ + +destroy a barrier that has waiting threads + + 0x........ + ... + BarrierErr + Destruction of a barrier with active waiters: barrier 0x........ + + + 0x........ + ... + pthread_barrier_destroy + ... + drd_pthread_intercepts.c + ... + + + 0x........ + ... + main + ... + bar_bad.c + ... + + + + barrier +
0x........
+ + + 0x........ + ... + pthread_barrier_init + ... + drd_pthread_intercepts.c + ... + + + 0x........ + ... + main + ... + bar_bad.c + ... + + +
+
+ + +destroy a barrier that was never initialised + + 0x........ + ... + GenericErr + Not a barrier + + + 0x........ + ... + pthread_barrier_destroy + ... + drd_pthread_intercepts.c + ... + + + 0x........ + ... + main + ... + bar_bad.c + ... + + + + + + + FINISHED + + + + + + ... + 0x........ + + + ... + 0x........ + + + ... + 0x........ + + + ... + 0x........ + + + ... + 0x........ + + + +... + +
+ diff --git a/helgrind/tests/Makefile.am b/helgrind/tests/Makefile.am index 8a0d6e650d..df82169fb3 100644 --- a/helgrind/tests/Makefile.am +++ b/helgrind/tests/Makefile.am @@ -19,6 +19,7 @@ EXTRA_DIST = \ cond_timedwait_test.vgtest cond_timedwait_test.stdout.exp \ cond_timedwait_test.stderr.exp \ bar_bad.vgtest bar_bad.stdout.exp bar_bad.stderr.exp \ + bar_bad.stderr.exp-destroy-hang \ bar_trivial.vgtest bar_trivial.stdout.exp bar_trivial.stderr.exp \ free_is_write.vgtest free_is_write.stdout.exp \ free_is_write.stderr.exp \ diff --git a/helgrind/tests/bar_bad.c b/helgrind/tests/bar_bad.c index dd6079c904..8ead816e17 100644 --- a/helgrind/tests/bar_bad.c +++ b/helgrind/tests/bar_bad.c @@ -15,23 +15,27 @@ void* child1 ( void* arg ) return NULL; } +void *sleep1 ( void* arg ) +{ + /* Long sleep, we hope to never trigger. */ + sleep (10); + pthread_barrier_wait ( (pthread_barrier_t*)arg ); + return NULL; +} + +void *exit1 ( void* arg ) +{ + /* Sleep a bit, then exit, we are done. */ + sleep (1); + exit (0); + return NULL; +} + int main ( void ) { pthread_barrier_t *bar1, *bar2, *bar3, *bar4, *bar5; - pthread_t thr1, thr2; int r; - - /* possibly set up a watchdog timer thread here. */ - - - - - - - - - - + pthread_t thr1, thr2, slp1, slp2, ext1; /* initialise a barrier with a zero count */ fprintf(stderr, "\ninitialise a barrier with zero count\n"); @@ -49,6 +53,9 @@ int main ( void ) fprintf(stderr, "\ninitialise a barrier which has threads waiting on it\n"); bar3 = malloc(sizeof(pthread_barrier_t)); pthread_barrier_init(bar3, NULL, 2); + /* create a thread, whose purpose is to "unblock" the barrier after + some sleeping in case it keeps being blocked. */ + pthread_create(&slp1, NULL, sleep1, (void*)bar3); /* create a thread, whose only purpose is to block on the barrier */ pthread_create(&thr1, NULL, child1, (void*)bar3); /* guarantee that it gets there first */ @@ -61,6 +68,12 @@ int main ( void ) /* once again, create a thread, whose only purpose is to block. */ bar4 = malloc(sizeof(pthread_barrier_t)); pthread_barrier_init(bar4, NULL, 2); + /* create a thread, whose purpose is to "unblock" the barrier after + some sleeping in case it keeps being blocked. We hope it isn't + needed, but if it is, because pthread_barier_destroy hangs + and we will get an extra warning about the barrier being already + destroyed. */ + pthread_create(&slp2, NULL, sleep1, (void*)bar4); /* create a thread, whose only purpose is to block on the barrier */ pthread_create(&thr2, NULL, child1, (void*)bar4); /* guarantee that it gets there first */ @@ -70,20 +83,24 @@ int main ( void ) /* destroy a barrier that was never initialised. This is a bit tricky, in that we have to fill the barrier with bytes which - ensure that the pthread_barrier_destroy call doesn't hang for - some reason. Zero-fill seems to work ok on amd64-linux (glibc + ensure that the pthread_barrier_destroy call doesn't crash for + some reason. One-fill seems to work ok on amd64-linux (glibc 2.8). */ fprintf(stderr, "\ndestroy a barrier that was never initialised\n"); + /* Create a thread that just exits the process after some sleep. + We are really done at this point, even if we hang. */ + pthread_create(&ext1, NULL, exit1, NULL); bar5 = malloc(sizeof(pthread_barrier_t)); assert(bar5); - memset(bar5, 0, sizeof(*bar5)); + memset(bar5, 1, sizeof(*bar5)); pthread_barrier_destroy(bar5); - /* now we need to clean up the mess .. */ - r= pthread_cancel(thr1); assert(!r); - r= pthread_cancel(thr2); assert(!r); + /* now we need to clean up the mess .. But skip canceling threads. */ + /* r= pthread_cancel(thr1); assert(!r); // drd doesn't like it. Just exit. + r= pthread_cancel(thr2); assert(!r); */ free(bar1); free(bar2); free(bar3); free(bar4); free(bar5); - return 0; + /* Use exit, we want to kill any "sleeper threads". */ + exit (0); } diff --git a/helgrind/tests/bar_bad.stderr.exp b/helgrind/tests/bar_bad.stderr.exp index 74af4fa562..d0901b2331 100644 --- a/helgrind/tests/bar_bad.stderr.exp +++ b/helgrind/tests/bar_bad.stderr.exp @@ -8,14 +8,14 @@ Thread #x is the program's root thread Thread #x: pthread_barrier_init: 'count' argument is zero at 0x........: pthread_barrier_init (hg_intercepts.c:...) - by 0x........: main (bar_bad.c:39) + by 0x........: main (bar_bad.c:43) ---------------------------------------------------------------- Thread #x's call to pthread_barrier_init failed with error code 22 (EINVAL: Invalid argument) at 0x........: pthread_barrier_init (hg_intercepts.c:...) - by 0x........: main (bar_bad.c:39) + by 0x........: main (bar_bad.c:43) initialise a barrier twice @@ -23,7 +23,7 @@ initialise a barrier twice Thread #x: pthread_barrier_init: barrier is already initialised at 0x........: pthread_barrier_init (hg_intercepts.c:...) - by 0x........: main (bar_bad.c:45) + by 0x........: main (bar_bad.c:49) initialise a barrier which has threads waiting on it @@ -31,13 +31,13 @@ initialise a barrier which has threads waiting on it Thread #x: pthread_barrier_init: barrier is already initialised at 0x........: pthread_barrier_init (hg_intercepts.c:...) - by 0x........: main (bar_bad.c:57) + by 0x........: main (bar_bad.c:64) ---------------------------------------------------------------- Thread #x: pthread_barrier_init: threads are waiting at barrier at 0x........: pthread_barrier_init (hg_intercepts.c:...) - by 0x........: main (bar_bad.c:57) + by 0x........: main (bar_bad.c:64) destroy a barrier that has waiting threads @@ -45,14 +45,14 @@ destroy a barrier that has waiting threads Thread #x: pthread_barrier_destroy: threads are waiting at barrier at 0x........: pthread_barrier_destroy (hg_intercepts.c:...) - by 0x........: main (bar_bad.c:69) + by 0x........: main (bar_bad.c:82) ---------------------------------------------------------------- Thread #x's call to pthread_barrier_destroy failed with error code 16 (EBUSY: Device or resource busy) at 0x........: pthread_barrier_destroy (hg_intercepts.c:...) - by 0x........: main (bar_bad.c:69) + by 0x........: main (bar_bad.c:82) destroy a barrier that was never initialised @@ -60,5 +60,5 @@ destroy a barrier that was never initialised Thread #x: pthread_barrier_destroy: barrier was never initialised at 0x........: pthread_barrier_destroy (hg_intercepts.c:...) - by 0x........: main (bar_bad.c:80) + by 0x........: main (bar_bad.c:96)