/* race.c Started by Jeff Ondich on 4/11/96 Last modified on 4/13/96 This program demonstrates how race conditions can occur when you use a "lock variable" strategy to try to avoid them. It also demonstrates simple creation and attachment of shared memory in linux. */ #include #include #include #include #include "race.h" #define lockKey ((key_t)2357) #define sharedIntKey ((key_t)1113) int *sharedInteger, *lock; /* global so InterruptHandler can detach */ char *CreateSharedMem( key_t, int ); void InterruptHandler( int ); void main( void ) { int pid, temp; signal( SIGINT, InterruptHandler ); /* Get and attach shared memory blocks */ lock = (int *)CreateSharedMem( lockKey, sizeof(int) ); sharedInteger = (int *)CreateSharedMem( sharedIntKey, sizeof(int) ); *lock = 0; /* Fork a child process */ pid = fork(); if( pid == -1 ) { perror( "fork() failure" ); exit( 1 ); } if( pid != 0 ) { /* Parent loops forever, putting 3's into the shared integer using the (flawed) lock variable technique. */ fprintf( stderr, "Parent [%d] starting\n", getpid() ); while( 1 ) { if( *lock == 0 ) { *lock = 1; *sharedInteger = 3; *lock = 0; } } } else { /* Child loops forever, putting 2's into the shared integer using the lock variable technique. If a race condition occurs, child reports it. */ fprintf( stderr, "Child [%d] starting\n", getpid() ); while( 1 ) { if( *lock == 0 ) { *lock = 1; *sharedInteger = 2; temp = *sharedInteger; *lock = 0; if( temp != 2 ) printf( "Race\n" ); } } } } /*********************************************** * * CreateSharedMem * * Create a "size"-byte * block of shared memory with the key. * CreateSharedMem() also attaches the shared * memory to the current process' address space, * and returns the attached address. ***********************************************/ char *CreateSharedMem( key_t key, int size ) { int id; char *sharedMemAddr; /* Create the shared memory. */ id = shmget( key, size, 0664 | IPC_CREAT | IPC_EXCL ); if( id == -1 ) { perror( "Shmget trouble" ); InterruptHandler( 0 ); } /* Attach the shared memory to the current process' address space. */ sharedMemAddr = (char *)shmat( id, (char *)0, 0 ); if( sharedMemAddr == (char *)-1 ) { perror( "Shmat trouble" ); InterruptHandler( 0 ); } return( sharedMemAddr ); } /*********************************************** * InterruptHandler * * Clean up IPC resources upon termination ***********************************************/ void InterruptHandler( int sig ) { int id; fprintf( stderr, "%d quitting\n", getpid() ); id = shmget( sharedIntKey, 0, 0 ); shmctl( id, IPC_RMID, NULL ); shmdt( sharedInteger ); id = shmget( lockKey, 0, 0 ); shmctl( id, IPC_RMID, NULL ); shmdt( lock ); exit( 1 ); }