deadlock quiz (was: How to do a pipe & fork?)

Maarten Litmaath maart at cs.vu.nl
Sat Nov 5 11:35:18 AEST 1988


\In article <Nov.2.14.51.36.1988.8260 at zztop.rutgers.edu>, pratt at zztop.rutgers.edu (Lorien Y. Pratt) writes:
\I have two processes that I want to communicate.  I want the parent to
\be able to fprintf to the child's stdin and to fscanf from the child's
\stdout.  I know that I need to fork and then in the child do an execlp,
\but I can't figure out how to set up the file descriptors so I can do
\what I want.

Other people already solved Lorien's problem, but the next is a related one.
I know why the following program doesn't work. The quiz is:
can YOU figure out why it fails? (Prizes to /dev/null.)
----------------------------------------------------------------------
#include	<stdio.h>
#include	<signal.h>

#define my_dup2(a, b)	(dup2(a, b) != -1 || panic("Dup failed"))

char	Text[] = "This is the text";
int	down[2], up[2];

main()
{
	char	*whoami;
	int	catch(), chpid;


	signal(SIGPIPE, catch);

	if (pipe(down) != 0)
		panic("error creating pipe down");

	if (pipe(up) != 0)
		panic("error creating pipe up");

	switch (chpid = fork()) {
		case -1:
			panic("Fork failed");
		case 0:
			whoami = "Child";
			do_child();
			break;
		default:
			whoami = "Parent";
			fprintf(stderr, "Child pid is %d\n", chpid);
			do_parent();
			break;
	}

	fprintf(stderr, "%s exits\n", whoami);
}

do_parent()
{
	FILE	*fp;
	char	buf[100];
	int	nr_read;


	fprintf(stderr, "Parent pipe\n");

	/* Connect write end of down to std output */

	close(1);
	my_dup2(down[1], 1);
	close(down[1]);

	/* Connect read end of up to std input */

	close(0);
	my_dup2(up[0], 0);
	close(up[0]);

	/* Convert output file descriptor to stream */

	if ((fp = fdopen(1, "w")) == NULL)
		panic("Can't convert descriptor to stream");

	fprintf(fp, "%s", Text);

	if (fclose(fp) == EOF)
		panic("Fclose failed");
		
	/* Child now sees EOF --> terminates */

	fprintf(stderr, "Just before read\n");

	/* Read results back from child */

	while ((nr_read = read(0, buf, sizeof buf)) > 0)
		fprintf(stderr, "received '%.*s'\n", nr_read, buf);
}

do_child()
{
	/* Connect read end of down to std input */

	close(0);
	my_dup2(down[0], 0);
	close(down[0]);

	/* Connect write end of up to std output */

	close(1);
	my_dup2(up[1], 1);
	close(up[1]);

	/* Exec the actual child program */

	fprintf(stderr, "Just before exec\n");
	execl("/bin/cat", "cat", (char *) 0);
	panic("Exec failed");
}

panic(msg)
char	*msg;
{
	fprintf(stderr, "Panic: %s\n", msg);
	exit(1);
}

catch(signo)
int	signo;
{
	if (signo == SIGPIPE)
		fprintf(stderr, "Pipe broken\n");
	else
		fprintf(stderr, "Signal %d\n", signo);
	exit(2);
}
-- 
George Bush:                          |Maarten Litmaath @ VU Amsterdam:
             Capt. Slip of the Tongue |maart at cs.vu.nl, mcvax!botter!maart



More information about the Comp.unix.wizards mailing list