/* 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;
}