user crashes machine on OSF/1 V3.2

From: Reinhard Doelz, Biocomputing Basel <doelz_at_comp.bioz.unibas.ch>
Date: Wed, 30 Aug 1995 17:43:39 +0200 (MDT)

Colleagues,

we have a weired problem on a AXP 4xxx system running OSF/1 3.2 and a
program which shall use (posix) shared memory and semaphores. The
execution of the program as a non-privileged user crashes the machine

trap: invalid memory write access from kernel mode

We suspect that the sem_unlink call might be faulty but upon booting
the device where the savecore should drop it is not recognized (?).


The source code is attached; it compiles as

cc crash_1.c -o crash_1 -non_shared -lrt
cc crash_2.c -o crash_2 -non_shared -lrt

and a screen trace is not informative - it just crashes and displays
the trap message on the console.

The program is stripped from a larger application and might contain some
non-needed stuff, but, basically, runs as follows:

o create a key file
o allocates a shared memory segment
o attach the segment
o write memory size to file
o creation of a semaphore
o write semaphore key name to file
o close semaphore
o reopen semaphore
o create a subprocess
                        forked ---> exec ------------> o read key file
o print 'setup ready' o open shared mem
 .... o open semaphores
dies in crash * CRASH *


Any help, pointers etc appreciated.

Regards
Reinhard Doelz
BioComputing Basel

#include <unistd.h>
#include <stdio.h>
#include <signal.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>

/* SYSV IPC calls */
#include <sys/ipc.h>
/*#include <sys/shm.h>*/
#include <sys/sem.h>

/* POSIX IPC calls */
#include <sys/mman.h>
#include <semaphore.h>

/* Linux doesn't know about TRUE or FALSE */
#ifndef TRUE
#define TRUE (1)
#endif

#ifndef FALSE
#define FALSE (0)
#endif

#define default_key 0xffff0000
#define default_size 20480
#define default_mode 0777

int shmid, semid;

static key_t shmkey = default_key;

pid_t cpid;

int num_chld;
int sleep_on;

FILE* keyfil;
FILE* infile;
FILE* outfile;

sem_t *master_go;
sem_t *slave_go;

char shmname[20];
char keyfilname[20];
char sem_name_m[20];
char sem_name_s[20];

char *buf; /* pointer to shared memory segment */

/* this program first writes, then reads the shared memory segment */

main()
{
        ushort state_array[6]; /* semaphore array for semctl(SETALL) */
        int flag_val; /* semaphore test: flag=semctl(GETVAL) */
        struct sembuf sem_act; /* semaphore operation command buffer */
        struct stat stat_buf;
        struct flock shm_lock;
        int num_sems;
        char sem_name[20];
        void bye();
        void not_chld();
        void time_out();
        int num_pages = 2; /* size of shared memory segment */
        size_t shm_size;
        size_t rsize = 1024; /* record size for fread() */
        size_t sys_pgsiz;
        char text[20];
        char dummy[20];
        pid_t rpid;
        int do_ipc = 1;
        int num, scan_len, numw;
        int status;
        int read_on, write_on, num_read, num_write, chunkr, chunkw;
        size_t head_len;

        /************** INITIAL SETUP *********************************/

        /* handle exceptions */

        atexit(bye); /* on any exit() call, run bye() */

        signal(SIGINT,bye); /* whenever a ^C is typed go to exit
                                   subroutine bye() */
        signal(SIGSEGV,bye); /* whenever a ^C is typed go to exit
                                   subroutine bye() */
/* signal(SIGSTOP,SIG_IGN);*/ /* whenever a ^Z is typed, ignore ! */

        signal(SIGALRM,time_out); /* whenever a timer interrupt occurs,
                                   clear sleep_on flag */

        signal(SIGCHLD,not_chld); /* whenever a child dies go to handler
                                   subroutine bye() */

        /* cleanup routine reading accidentially left key files ?? */

        /* shared memory setup */

        /* first allocate a shared memory segtment */

        /* the ftok call isn't available on all systems! */
        /* we need a shmem-key: simple ftok-hack with tmpfile */
        printf("master: creating key file ... ");

        sprintf(shmname,"master_XXXXXX");
        mktemp(shmname);

        printf("key file is %s\n", shmname);

        sprintf(keyfilname,"%s_K",shmname);
        keyfil = fopen(keyfilname,"w+");
        printf("key file is %s\n", keyfilname);

        /* create key based on inode no. of tmpfile and minor no. of dev */
        printf ("master: create key ... ");
        stat(keyfilname,&stat_buf);
        shmkey = (key_t) stat_buf.st_ino;
        shmkey = shmkey<<8 + (unsigned)(stat_buf.st_dev>>8);

        printf (" %d %X\n", shmkey, shmkey);

        /* write key into file for the slave to read */
        fprintf(keyfil,"Key : %d size : %d\n",shmkey, num_pages);

        /* make key file name available to slave via environment */
        sprintf(dummy,"IPC_KEY=%s", keyfilname);
        putenv(dummy);

        /* make sure it _is_ available */
        if (getenv("IPC_KEY")) {
          printf("master: set env. \"IPC_KEY=%s\"\n", getenv("IPC_KEY"));
        } else {
          printf("can't re-read shmem name !\n");
          exit (1);
        }

        printf ("master: get ID ... ");
        /* POSIX : getting shmID is getting a _file descriptor_ from a name! */

        if((shmid = shm_open(shmname,O_CREAT|O_RDWR,0770)) < 0) {
                perror("shm_open");
                exit(0);
        }

        printf (": %d\n", shmid);

        /* before we can use the section, we have to 'ftruncate' the size! */
        /* size is page-aligned !!! on AXP */
        sys_pgsiz = sysconf(_SC_PAGE_SIZE);
        shm_size = num_pages*sys_pgsiz;
        if ((ftruncate(shmid, shm_size)) == -1) {
          perror ("shmem ftruncate()");
          exit(-1);
        }

        /* 'attach' done by a mmap() call - as would be used for files */
        printf ("master: attach segment ...");
        if((long) (buf = mmap(0, shm_size , PROT_READ|PROT_WRITE,
                              MAP_SHARED, shmid, 0)) < 0) {
                perror("mmap");
                exit(0);
        }
        printf (": %X\n", buf);

        /* no memset() required ... */

        /* end of shared memory setup */

        /* semaphore setup */

        printf("master: get semaphores ... using key %d\n",shmkey);

        /* Open semaphore - reuse shmkey ! */
        if( ( semid=semget(shmkey,6,0777|IPC_CREAT)) == -1) {
                printf("\n Can't open semaphor ( master ) \n");
                perror("semget");
                fflush(stdout);
                bye();
        }

        num_sems = 0;
        /* Open POSIX semaphore - create unique name ! */
        sprintf(sem_name_m,"%s_S%d", shmname, ++num_sems);
        printf("master: semaphore %d: %s\n", num_sems, sem_name_m);
        if ((master_go=sem_open(sem_name_m,O_CREAT,0640,0))==(void *)-1){
          perror("sem_open (create)");
          bye();
        }
        /* write semname into file for the slave to read */
        fprintf(keyfil,"Sem : %s\n", sem_name_m);

#define CAUSE_TROUBLE
#ifdef CAUSE_TROUBLE
        if ((sem_close(master_go))==-1){
          perror("sem_close (create)");
          bye();
        }
        if ((master_go=sem_open(sem_name_m,O_RDWR,0640))==(void *)-1){
          perror("sem_open (open)");
          bye();
        }
#endif
        /* Open POSIX semaphore - create unique name ! */
        sprintf(sem_name_s,"%s_S%d", shmname, ++num_sems);
        printf("master: semaphore %d: %s\n", num_sems, sem_name_s);
        if ((slave_go=sem_open(sem_name_s,O_CREAT,0640,0))==(void *)-1){
          perror("sem_open (create)");
          bye();
        }
        /* write semname into file for the slave to read */
        fprintf(keyfil,"Sem : %s\n", sem_name_s);
#ifdef CAUSE_TROUBLE
        if ((sem_close(slave_go))==-1){
          perror("sem_close (create)");
          bye();
        }
        if ((slave_go=sem_open(sem_name_s,O_RDWR,0640))==(void *)-1){
          perror("sem_open (open)");
          bye();
        }
#endif
        /*
        ** first init semaphore array for synchronization !
        */

        state_array[4] = state_array[5] = 1 ;

        printf("master: setting semaphores : %d %d ...\n",
               state_array[0], state_array[1]);
        /* write-test semaphore status */
        if( semctl(semid,6,SETALL,state_array) == -1 ) {
                printf("\n Can't do semctl SETALL ( master )\n");
                fflush(stdout);
                bye();
        }

        /* semaphore array reset for synchronization _now_ ! */

        fflush(stdout);

        fclose(keyfil);

        /* end of semaphore setup */

        /********************** END OF INITIAL SETUP *************************/


        /*********************** SUBPROCESS CREATION *************************/

        /* 'slave' process creation and verification */
        /* fork away to exec slave process */

        if ( (cpid = fork()) == 0 ){ /* the 'child' process (!= slave !) */
          printf ("child : exec'ing image\n");

          if (execl("./crash_2", "crash_2", NULL) == -1)
                  perror ("execl");

          printf("child : execl() failed !\n");
          /* no point in running two master processes ! */
          exit(1); /* child here: should't try deallocating shmem !! */
        } else { /* the 'parent' process (== master) */
          if (cpid < 0) {
            printf ("parent: fork() failed, exiting!\n");
            /* did you ever try a kill(-1) ? - hold your breath ! */
            cpid = 0;
            bye();
          }
          printf("parent: forked child pid %d\n", cpid);

          num_chld++;
          numw = 0;
          while ((rpid=waitpid(cpid,&status, WNOHANG)) == 0 && ++numw < 10)
            usleep(10000);

          /* check for wait() condition */
          if (cpid == rpid) {
            printf ("parent: child found after %d attempts!\n", numw);
            if (!WIFEXITED(status) && !WIFSIGNALED(status)) {
              /* this seems ok ... */
              printf("parent: child %d still alive!\n", cpid);
            } else {
              /* any of these mean that child is dead ... */
              if (WIFEXITED(status))
                printf ("parent: child %d exited with status %d\n",
                     cpid, WEXITSTATUS(status));
              if (WIFSIGNALED(status))
                printf("parent: child %d terminated with signal %d!\n",
                     cpid, WTERMSIG(status));
              /* no point in waiting for input from dead child! */
              bye();
            } /* end wait()-status */
          } /* end cpid == wait() */
        
        } /* end fork() */

        /* end of process creation and verification */

        /******************** END SUBPROCESS CREATION ************************/

        printf("master: process setup ready !\n");

        /* once we are here, both master and slave are alive ! */

        /* initialize memory segment */

        *buf = '\0';
        memset (buf, 0, shm_size*sizeof(char));


        state_array[0] = state_array[1] = 0 ;
        state_array[2] = 0 ;

        if( semctl(semid,6,SETALL,state_array) == -1 ) {
                printf("\n Can't do semctl SETALL ( master )\n");
                fflush(stdout);
                bye();
        }

#ifndef LOCK_SEM
        /* the 'initiator' process first reserves the exclusive lock */

        /* apply exclusive lock ( prevent slave getting read lock)
        ** by nonblocking request - if we fail, someone else has the lock!
        */
        shm_lock.l_type = F_WRLCK;
        shm_lock.l_whence = SEEK_SET;
        shm_lock.l_start = 0;
        shm_lock.l_len = shm_size;
        
        if ((fcntl(shmid, F_SETLK, &shm_lock)) == -1) {
          printf ("master: fcntl(wlk) failed!");
          bye();
        }
#endif

        /* trigger slave */

        if ((sem_post(slave_go)) == -1) {
          perror("sem_post (->slave)");
          bye();
        }

        /* wait for ack */

        sleep_on = 1;
        alarm(10); /* set timeout watchdog */
        /*************** SLEEP ***************/
        if((sem_wait(master_go)) == -1 ) {
          /* sleep interruptible */
          if (errno == EINTR) {
            printf ("master: sem(w) wait interrupted !\n");
            if (!sleep_on) {
              printf ("master: semwait timed out, aborting !\n");
              alarm(0);
              bye(); /* could return to other work here ... */
            }
          } else {
            perror ("sem_wait (<-slave)");
            bye();
          }
        }
        alarm(0);
        sleep_on = 0;
        
        /* try to cause trouble */
         sleep (100);

          
        /* end of communication */

        bye();

}

void bye() /* here is where the shared memory segment is deleted */
{
  char sem_name[50];
  key_t key;
  int siz;
  int status, num_pages = 2;

  /* we want to clean up here without being interrupted by the children */
  signal(SIGCHLD, SIG_IGN);

  signal(SIGINT,SIG_DFL); /* whenever a ^C is typed , die */
  signal(SIGALRM,SIG_IGN); /* whenever a timeout comes - ignore */

  alarm(0); /* reset alarm clock */

  /* for multiple children: place a loop over cpid[] here */
  if (cpid > 0) { /* doing a kill(-pid) ain't funny :-( */
    printf("parent: waiting for child %d to die ...",cpid);
    if (!kill(cpid, SIGTERM)) {
      /*
       ** CAUTION : if the signal handler for SIGCHLD is still active,
       ** the rest of this routine is not executed for the last child
       ** being killed !!
       */
      printf(" killed %d !\n",cpid);
      if (cpid == waitpid(cpid,&status,0)) {
        printf("parent: child delivered signal SIGCHLD\n");
        if (WIFEXITED(status))
          printf ("parent: child %d exited with status %d\n",
                  cpid, WEXITSTATUS(status));
        if (WIFSIGNALED(status))
          printf("parent: child %d received signal %d!\n",
                 cpid, WTERMSIG(status));
        if (!WIFEXITED(status) && !WIFSIGNALED(status))
          printf("parent: child %d still alive!\n", cpid);
      }
    } else
      printf (" kill failed !\n");
    cpid = 0;
  }

  printf ("parent: bye() continuing \n");
  
  /* release and delete memory segment */
  if (( munmap(buf, num_pages*sysconf(_SC_PAGE_SIZE)) ) == -1)
    perror("munmap");
  if ((close(shmid)) == -1)
    perror("shmem close");
  if((shm_unlink(shmname)) == -1)
    perror("shm_unlink");
  
  /* release and delete IPC semaphore */
  if( semctl(semid, 2 , IPC_RMID, 0 ) < 0 ) {
    perror("semctl");
  }
  /* release and delete POSIX semaphore */
  /* need to have array of created sem_ptrs here, sorry */

  /* unlink POSIX semaphores */
  if (master_go) {
    printf("master: closing sem. %X\n", master_go);
    if ((sem_close(master_go)) == -1)
      perror ("sem_close");
  }
  if (slave_go) {
    printf("master: closing sem. %X\n", slave_go);
    if ((sem_close(slave_go)) == -1)
      perror ("sem_close");
  }

  /* doesn't work either ... ?? */

  /* sleep here to wait for slave to free semaphores */

  printf ("master: sleeping before sem_unlink ...\n");
  fflush (stdout);

  sleep(5);

  printf ("master: unlinking sem. <%s>\n", sem_name_m);
  if ((sem_unlink(sem_name_m)) == -1)
    perror ("sem_unlink");

  printf ("master: unlinking sem. <%s>\n", sem_name_s);
  if ((sem_unlink(sem_name_s)) == -1)
    perror ("sem_unlink");

  if ((unlink(sem_name_m)) == -1)
    perror ("unlink");
  if ((unlink(sem_name_s)) == -1)
    perror ("unlink");

/* doesn't work .. */
/*
  printf ("master: re-opening key file %s ...\n", getenv("IPC_KEY"));
  if ((keyfil = fopen(getenv("IPC_KEY"),"r")) != NULL) {
    fscanf(keyfil,"Key : %d size : %d\n", &key, &siz);
    printf ("master: read key %d size %d \n", key, siz);
    while ((fscanf(keyfil,"Sem : %s\n",sem_name)) != EOF) {
      printf ("master: read Sem. name ... %s \n",sem_name);
      if ((sem_unlink(sem_name)) == -1)
        perror ("sem_unlink");
    }
    fclose(keyfil);
  } else {
    printf("can't open key file for segment !\n");
  }
*/
  /* remove key file pointing to memory segment*/
  if (keyfil) fclose(keyfil);
  unlink(keyfilname);
  
  printf("exiting normally\n");
  _exit(1);
}

void not_chld() /* here is where the death of a child process is handled */
{
  char sem_name[50];
  key_t key;
  int siz;
  int status, num_pages = 2;

  signal(SIGALRM,SIG_IGN); /* whenever a timeout comes - ignore! */

  alarm(0); /* reset timeout */

  printf ("parent: caught SIGCHLD !\n");
  fflush (stdout);

  /* get child pid */
  if ((cpid == waitpid(0,&status,0)) > 0) {
    /* decrease number of childs so we know when there are no more left */
    num_chld--;
    /* clear entry in children table */
    /* post-mortem analysis */
    printf("parent: child delivered signal SIGCHLD\n");
    /* voluntary (or crash) exit */
    if (WIFEXITED(status))
      printf ("parent: child %d exited with status %d\n",
              cpid, WEXITSTATUS(status));
    /* caught signal */
    if (WIFSIGNALED(status))
      printf("parent: child %d received signal %d!\n",
             cpid, WTERMSIG(status));
    /* other reason */
    if (!WIFEXITED(status) && !WIFSIGNALED(status))
      printf("parent: child %d - undefined fate!\n", cpid);
  }

  printf ("parent: not_chld() continuing \n");

  /* if there are any more childs active, continue */
  if ( num_chld > 0 ) {
    printf ("parent: child buried; returning to work !\n");
    fflush (stdout);
    return;
  }
  /* release and delete memory segment */
  if (( munmap(buf, num_pages*sysconf(_SC_PAGE_SIZE)) ) == -1)
    perror("munmap");
  if ((close(shmid)) == -1)
    perror("shmem close");
  if((shm_unlink(shmname)) == -1)
    perror("shm_unlink");

  /* release and delete semaphores */
  if( semctl(semid, 2 , IPC_RMID, 0 ) < 0 ) {
    perror("semctl");
  }

  /* release and delete POSIX semaphore */
  /* need to have array of created sem_ptrs here, sorry */

  if (master_go) {
    printf("master: closing sem. %X\n", master_go);
    sem_post(master_go);
    if ((sem_close(master_go)) == -1)
      perror ("sem_close");
  }
  if (slave_go) {
    printf("master: closing sem. %X\n", slave_go);
    sem_post(slave_go);
    if ((sem_close(slave_go)) == -1)
      perror ("sem_close");
  }

  /* sleep here to wait for slave to free semaphores */

  sleep(5);

  printf ("master: unlinking sem. <%s>\n", sem_name_m);
  if ((sem_unlink(sem_name_m)) == -1)
    perror ("sem_unlink");

  printf ("master: unlinking sem. <%s>\n", sem_name_s);
  if ((sem_unlink(sem_name_s)) == -1)
    perror ("sem_unlink");

  if ((unlink(sem_name_m)) == -1)
    perror ("unlink");
  if ((unlink(sem_name_s)) == -1)
    perror ("unlink");

  /* unlink POSIX semaphores */
/*
  printf ("master: re-opening key file %s ...\n", getenv("IPC_KEY"));
  if ((keyfil = fopen(getenv("IPC_KEY"),"r")) != NULL) {
    fscanf(keyfil,"Key : %d size : %d\n", &key, &siz);
    printf ("master: read key %d size %d \n", key, siz);
    while ((fscanf(keyfil,"Sem : %s\n",sem_name)) != EOF) {
      printf ("master: read Sem. name ... %s \n",sem_name);
      if ((sem_unlink(sem_name)) == -1)
        perror ("sem_unlink");
    }
    fclose(keyfil);
  } else {
    printf("can't open key file for segment !\n");
  }
*/
  /* remove key file pointing to memory segment and semaphores */
  if (keyfil) fclose(keyfil);
  unlink(keyfilname);
  
  printf ("parent: No more childs alive, so I'll die !\n");
  fflush (stdout);
  
  _exit(1);
}

void time_out()
{
  if (sleep_on) {
    printf (" -> wait timed out ! \n");
    sleep_on = 0;
    fflush (stdout);
  }
  return;
}

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>

/* SYSV IPC */
#include <sys/ipc.h>
/*#include <sys/shm.h>*/
#include <sys/sem.h>

/* POSIX IPC */
#include <sys/mman.h>
#include <semaphore.h>

#ifndef TRUE
#define TRUE (1)
#endif

#ifndef FALSE
#define FALSE (0)
#endif

#define default_key 0xffff0000
#define default_size 20480
#define default_mode 0777

int shmid, semid;
static key_t shmkey = default_key;

int sleep_on;

char *buf;
char keyfilname[20];

sem_t *master_go;
sem_t *slave_go;

FILE* keyfil;
FILE* infile;
FILE* outfile;

/* this program writes to the shared memory segment */

main()
{
        char line[1024];
        int num_pages = 2;
        static size_t rsize = 1024; /* record size for fread() */
        size_t shm_size;
        size_t sys_pgsiz;
        ushort state_array[2];
        int flag_val;
        struct sembuf sem_act;
        struct stat stat_buf;
        struct flock shm_lock;
        int num_sems;
        char sem_name[20];
        void finish();
        void time_out();
        char shmname[20];
        int i, j=0;
        key_t shmkey2;
        int read_on, write_on, num_read, num_write, chunkr, chunkw;
        size_t head_len;
        int file_ready;
        int semvalue_m, semvalue_s;

        /* exit and signal handling */

        atexit(finish);

        signal(SIGTSTP, SIG_IGN); /* ignore output stop */

        signal(SIGTERM, finish); /* clean up on TERM */

        signal(SIGALRM, time_out); /* whenever a timer interrupt occurs,
                                   clear sleep_on flag */

        /* shared memory setup */

                                /* first allocate a shared memory segtment */
        printf ("slave : get segment name ... ");

        /* read key file name from environment */

        if (getenv("IPC_KEY")) {
          sprintf(keyfilname,"%s", getenv("IPC_KEY"));
        } else {
          printf("can't get segment name !\n");
          exit (1);
        }

        /* need not open the file except for reading the size e.g. */

        keyfil = fopen(keyfilname,"r");
        printf (" read key ... ");
        fscanf(keyfil,"Key : %d size : %d\n",&shmkey, &num_pages);

        /* segment name is keyfilname without trailing _K */

        if (strncpy(shmname, keyfilname, strlen(keyfilname)-2) == NULL)
          perror ("strncpy");

        printf ("slave : segment name is %s \n", shmname);

        printf (" done: %s %d\n", shmname, shmkey);

        /* POSIX : getting shmID is getting a _file descriptor_ from a name! */
        printf ("slave : get ID ... ");

        if((shmid = shm_open(shmname,O_RDWR,0770)) < 0) {
                perror("shm_open");
                exit(0);
        }
        printf (": %d\n", shmid);

        /* before we can use the section, we have to 'ftruncate' the size! */
        sys_pgsiz = sysconf(_SC_PAGE_SIZE);
        if ((ftruncate(shmid,num_pages*sys_pgsiz)) == -1) {
          perror ("shmem ftruncate()");
          exit(-1);
        }
        /* 'attach' done by a mmap() call - as would be used for files */
        printf ("slave : attach segment ...");
        if((long) (buf = mmap(0, num_pages*sys_pgsiz , PROT_READ|PROT_WRITE,
                              MAP_SHARED, shmid, 0)) < 0) {
                perror("mmap");
                exit(0);
        }
        printf (": %X\n", buf);
        fflush (stdout);

        /* end of shared memory setup */

        /* semaphore setup */

        printf("slave : get semaphores ... using key %d \n",shmkey);

        /* Open semaphore - reuse shmkey ! */
        if( ( semid=semget(shmkey,6,0777)) == -1) {
                printf("\n Can't open semaphor ( slave ) \n");
                perror("semget");
                fflush(stdout);
                exit(-1);
        }

        num_sems = 0;
        fscanf(keyfil,"Sem : %s\n", sem_name);
        printf("slave : semaphore %d: >%s<\n", ++num_sems, sem_name);
        if ((master_go=sem_open(sem_name,O_RDWR,0640))==(void *)-1) {
          perror("sem_open");
          exit(-1);
        }

        fscanf(keyfil,"Sem : %s\n", sem_name);
        printf("slave : semaphore %d: >%s<\n", ++num_sems, sem_name);
        if ((slave_go=sem_open(sem_name,O_RDWR,0640))==(void *)-1) {
          perror("sem_open");
          exit(-1);
        }

        /* end semaphore setup */

        fclose(keyfil);

        /* wait until triggered by the master - use state_array[5] */
#define SEM_POSIX
#ifdef SEM_POSIX

        /* wait for request */
        sleep_on = 1;
        alarm(10); /* set timeout watchdog */
        /*************** SLEEP ***************/
        if((sem_wait(slave_go)) == -1 ) {
          /* sleep interruptible */
          if (errno == EINTR) {
            printf ("slave : sem(i) wait interrupted !\n");
            if (!sleep_on) {
              printf ("slave : semwait timed out, aborting !\n");
              alarm(0);
              exit(-1); /* could return to other work here ... */
            }
          } else {
            perror ("sem_wait (<-master)");
            exit(-1);
          }
        }
        alarm(0);
        sleep_on = 0;
#endif

        /* trigger master */
        if ((sem_post(master_go)) == -1) {
          perror("sem_post (->slave)");
          exit(-1);
        }

        if ((sem_getvalue(master_go,&semvalue_m)) == -1)
          perror("getvalue (master_go)");
        if ((sem_getvalue(slave_go,&semvalue_s)) == -1)
          perror("getvalue (slave_go)");

        printf ("slave : semvalues %d %d\n", semvalue_m, semvalue_s);

        /* delay here confuses slave, as master proceeds to may_read */
        /* if 0 0 2 is used for init - no problem with 0 0 0 */
        /* sleep (5); */

#define CHECK_INIT
#ifdef CHECK_INIT
        if( semctl(semid,6,GETALL,state_array) == -1 ) {
          printf("\n Can't do semctl GETALL ( master )\n");
          fflush(stdout);
          exit(-1);
        }
        printf ("slave : state array is %d %d %d !\n", state_array[0],
                state_array[1], state_array[2]);
        fflush(stdout);

#endif
        /* semaphore array reset for synchronization _now_ ! */

        /* end of semaphore setup */

        /* communication begins */

        sleep(60);

        /* communication ends with kill() by parent for now! */

}

void finish() /* here is where the shared memory segment is deleted */
{
  int rv, num_pages;
  char shmname[20], sem_name[20];
  static int exit_done = 0;

  if (exit_done) exit(1);

  shmname[0] = '\0';
  /* re-get the env. info
  if (getenv("IPC_KEY") == NULL) {
    printf ("can't get segment name !\n");
    num_pages = 2;
  }

  /* need to open the key file for reading the size !! */
  printf ("slave : reopening %s ", getenv("IPC_KEY"));
  fflush (stdout);
  
  if ((keyfil = fopen(getenv("IPC_KEY"),"r")) != NULL) {
    fscanf(keyfil,"Key : %d size : %d\n",&shmkey, &num_pages);
    printf (", read key ... %d \n",shmkey);
  } else {
    printf("can't open key file for segment !\n");
    num_pages = 2;
  }

  /* detach memory segment - deleted by master */
  if (( rv=munmap(buf, num_pages*sysconf(_SC_PAGE_SIZE)) ) == -1)
    perror("munmap");
  if (shmid) {
    if ((rv=close(shmid)) == -1)
      perror("shmem close");
    if (rv == 0) shmid = 0;
  }

  /* release and delete IPC semaphore: done by master */

  /* release POSIX semaphore (_not_ done automagically ??) */

  if (master_go) {
    printf("slave : closing sem. %X\n", master_go);
    if ((rv=sem_close(master_go)) == -1)
      perror("sem_close (slave)");
    if (rv == 0) master_go = NULL;
  }
  if (slave_go) {
    printf("slave : closing sem. %X\n", slave_go);
    if ((rv=sem_close(slave_go)) == -1)
      perror("sem_close (slave)");
    if (rv == 0) slave_go = NULL;
  }

  if (keyfil) {
    while ((fscanf(keyfil,"Sem : %s\n",sem_name)) != EOF) {
      printf ("slave : read Sem. name : <%s> , unlinking\n",sem_name);
      if ((sem_unlink(sem_name)) == -1)
        perror ("sem_unlink");
    }
    fclose(keyfil);
  } else {
    printf("key file for segment not open!\n");
  }
  
  /* remove key file pointing to memory segment: done by master*/
  
  printf("exiting normally\n");

  exit_done = 1;
  exit(1);
}

void time_out()
{
  sleep_on = 0;
  printf (" -> wait timed out ! \n");
  fflush (stdout);
  return;
}
Received on Wed Aug 30 1995 - 18:45:29 NZST

This archive was generated by hypermail 2.4.0 : Wed Nov 08 2023 - 11:53:45 NZDT