1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
|
/* 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;
}
|