Path: utzoo!utgpu!attcan!uunet!mcvax!hp4nl!telmail!root From: root@telmail.UUCP (Super user) Newsgroups: comp.unix.xenix Subject: Re: Test SCO Xenix IPC reliability Keywords: ipc reliability Message-ID: <114@telmail.UUCP> Date: 25 Aug 88 18:05:56 GMT References: <22012@neabbs.UUCP> <5786@rpp386.UUCP> Reply-To: root@telemail.UUCP (Richard Ronteltap) Organization: NEABBS multi-line BBS 31-20-717666 Amsterdam, Netherlands Lines: 116 In article <5786@rpp386.UUCP> jfh@rpp386.UUCP (The Beach Bum) writes: >this program should work regardless of scheduling. on the first entry >into child() the busy loop will be executed because loc[0] was set to >zero prior to the fork. the signal handler was set prior to entry to >child (but should have been set before the fork() - stupid me). > >if parent() executes the kill() call before the child() executes the >signal() call, then you should have seen TICK ... with a hang forever. >the fix is to move the signal() call to before the fork(). if ... TOCK >is printed then signal() has been called. That's not what I said in my article. Just to be sure, I've tried to move the signal() before the fork, but got exactly the same results. I'll try to explain again with a little code: When I start the program the first time, I get 1 TICK/TOCK. The second time I get infinite TICK/TOCK's. The result of the first time is caused by unfortunate scheduling, I think, and here's why (first the fragment): >parent () >{ > while (1) { > while (*loc) > ; > > write (1, "TICK ....\n", 10); > *loc = 1; > kill (loc[2], SIGUSR1); > pause (); > } >} > >child () >{ > while (1) { > while (! *loc) > ; > > write (1, ".... TOCK\n", 10); > *loc = 0; > kill (loc[1], SIGUSR1); > pause (); > } >} Because loc[0] was initialised to 0, the child process waits if it happens to get to the 'while' loop first. The parent process passes the loop, prints TICK, changes *loc to 1 and signals the child process. AT THIS INSTANT, i.e. BEFORE the parent reaches pause(), the scheduler transfers control to the child process. (btw is this possible?) The child process prints TOCK, sets *loc to 0, signals the parent, and pauses. The parent catches the signal, and continues with the next instruction: THE PAUSE() INSTRUCTION, and waits for a signal from the child forever. Get it? I don't know if the signals were a relevent part of the testing procedure, but I've 'rewritten' the program without them, and it works just fine. Of course it doesn't run as fast because of massive waiting in the 'while' loops, waiting for the scheduler to transfer control to the child or vice versa. Here is the new program: ------------------------------------------------------------------- #include #include #include int *loc; int key = ('v' << 8) | 'o'; parent () { while (1) { while (*loc) ; write (1, "TICK ....\n", 10); *loc = 1; } } child () { while (1) { while (! *loc) ; write (1, ".... TOCK\n", 10); *loc = 0; } } main () { int id; if ((id = shmget (key, sizeof (int), IPC_CREAT|0666)) == -1) { perror ("shmget"); exit (1); } if ((loc = (int *) shmat (id, (char *) 0, 0)) == (int *) 0) { perror ("shmat"); exit (1); } *loc = 0; switch (fork ()) { case -1: perror ("fork"); exit (1); case 0: child (); default: parent (); } exit (1); } ---------------------------------------------------------- Richard (...!mcvax!neabbs!richard)