Test SCO Xenix IPC reliability

Super user root at telmail.UUCP
Fri Aug 26 04:05:56 AEST 1988


In article <5786 at rpp386.UUCP> jfh at 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 <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>

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)



More information about the Comp.unix.xenix mailing list