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