/* Check that a child thread doesn't inherit its parent's disablement status. */ #include <stdlib.h> #include <stdio.h> #include <assert.h> #include <pthread.h> #include <unistd.h> // sleep #include "../include/valgrind.h" char* block = NULL; __attribute__((noinline)) void usechar ( char c ) { // Spook gcc into believing mysterious bad things are // happening behind its back, and that 'c' is definitely // used in some (unknown) way. __asm__ __volatile__("" : : "r"(c) : "memory","cc"); } __attribute__((noinline)) void err ( void ) { usechar( block[5] ); } void* child_fn ( void* arg ) { fprintf(stderr, "\n--------- c: start (expect 1) ---------\n\n"); err(); fprintf(stderr, "\n--------- c: end ---------\n\n"); return NULL; } int main ( void ) { int r; pthread_t child; block = malloc(10); free(block); fprintf(stderr, "\n--------- p: disabling errors (expect 0) ---------\n\n"); VALGRIND_DISABLE_ERROR_REPORTING; err(); fprintf(stderr, "\n--------- p: creating child ---------\n\n"); r = pthread_create(&child, NULL, child_fn, NULL); assert(!r); sleep(1); // let the child run first (determinism fix) fprintf(stderr, "\n--------- p: join child ---------\n\n"); r = pthread_join(child, NULL); assert(!r); fprintf(stderr, "\n--------- p: re_enabled (expect 1) ---------\n\n"); VALGRIND_ENABLE_ERROR_REPORTING; err(); return 0; }