Jump to content

Pipes and forks issue in C

- - - - -

This topic has been archived. This means that you cannot reply to this topic.
4 replies to this topic

#1
redcameron

redcameron

    Newbie

  • Members
  • Pip
  • 3 posts
So I'm having some trouble with a C program that forks n processes of which each child communicates information back to the parent. What I've done is written a main function that handles all this:


void master_process() {

	int pid;

	maps_list = (map_details *) emalloc(sizeof(map_details) * num_mappers);

	distribute_files();

	for (map_count = 0; map_count < num_mappers; map_count++) {

		if (pipe(maps_list[map_count].fd) == -1) {

			perror("pipe");

			exit(1);

		}

		if ((pid = fork()) == 0) {

			child_process();

		} else if (pid > 0) {

			maps_list[map_count].status = 0;

			maps_list[map_count].pid = pid;

			printf("%d\n", pid);

			close(maps_list[map_count].fd[1]);

		} else {

			perror("form");

			exit(1);

		}

	}

	printf("call parent here\n");

	parent_process();

	exit(1);

}


The child process looks like so:


void child_process() {

	close(maps_list[map_count].fd[0]);

	int i;

	int begin_file = map_count * maps_list[map_count].files_to_process;

	int end_file = ceil(begin_file + maps_list[map_count].files_to_process - 1);	

	FILE *fp;

	chdir(input_path);

	

	for (i = begin_file; i < end_file; i++) {

		printf("scan: %s\n", file_list[i]->d_name);

		if ((fp = fopen(file_list[i]->d_name, "r")) == NULL) {

			perror(file_list[i]->d_name);

			exit(1);

		}

		map(fp, maps_list[map_count].fd[1]);

		fclose(fp);

	}

	printf("ended process %d\n", map_count);

	exit(0);

}


and the parent looks like:


void parent_process() {

	int count, status, pid, n;

	char buf[256];

	

	for (count = 0; count < num_mappers; count++) {

		while ((n = read(maps_list[count].fd[1], buf, 256)) > 0) {

			printf("%s\n", buf);

		}

	}

	for (count = 0; count < num_mappers; count++) {

		if ((pid = wait(&status)) == -1) {

			perror("wait");

		} else {

			if (WIFEXITED(status)) {

				printf("Proces %d exited with %d\n", pid, WEXITSTATUS(status));

			}

		}		

	}

}


Without posting more code than I need to, the child calls a function called map which handles my file and does something with it. Sends the data back as:


	    if (write(fd, r, RECORDSIZE) != RECORDSIZE) {

		perror("write");

		exit(1);

	    }


Basically I'm pretty sure I've got the pipes setup properly and I AM receiving data through the pipe but it doesn't appear to be accurate. For example if I dynamically set my script to split off only 1 child process the program seems to hang waiting for the child to give it data.

If I have 4 children then it seems to not be sending ALL the data back to the parent. If you're wondering, this indeed a school assignment and my code may seem n00bish. Apologies. I want to love C, but the subtle things are killing me. Heh.

I'm most likely not doing something properly with waiting of reading the data...maybe the children are sending data BEFORE the parent is set to read it?

Help is greatly appreciated.

Cheers.

Dave

So digging a bit deeper this morning, I realised that the reason the program is hanging is due to a child which just doesn't want to end its process. I'm doing a file read in the child but that seems to be working, else it should exit with status 1 at least.

This is making me believe that it's something to do with picking up data from the child. Apparently the child wont quit until its write is received. So I modified my parent to:


	while (mappers_reported() == 0) {

		for (count = 0; count < num_mappers; count++) {

			while ((n = read(maps_list[count].fd[1], buf, recordsize)) > 0) {

				printf("%s\n", buf);

				maps_list[count].status = 1;

			}

		}

	}


mappers_reported is a simple function which looks through the mapper struct details I created, and checks if it assigned 1 when reading in the while loop. An temp kluge to determine if this is indeed the case.

Furthermore I'm starting to realise that the FIRST process that is forked seems to be holding the entire thing up. It just doesn't want to close. It happens specifically on the LAST file. So if I input 9 files to scan in my process it will do all of them except the LAST file. I doubt it's segfaulting or anything like that...

Still super worried and confused. :(

Uhm so I'm getting closer to a solution, but I'm literally at a point where I have no idea what to do. Seems like my program is completely not receiving data from the FIRST child process. Why, I have no idea?

My assumption is that the child begins writing to the parent but the data isn't picked up until the parent actually does a read. So the data will just sit waiting until it's time. I'm guessing that my logic is flawed here.

The question is how to repair my code now :-/

I've attached my master C file in case someone is interested in helping out. Heh. $15 (a few good beers) for the winning solution? Common, I'm disparate here. lol.

Attached Files


Edited by WingedPanther, 24 March 2009 - 11:23 AM.
triple post


#2
WingedPanther

WingedPanther

    A spammer's worst nightmare

  • Moderators
  • 16,831 posts
Can you offer some more details, such as the OS/mechanism you are using? Forks and pipes are not part of C itself, as far as I know.
Programming is a branch of mathematics.
My CodeCall Blog | My Personal Blog

#3
redcameron

redcameron

    Newbie

  • Members
  • Pip
  • 3 posts
Yup on I'm Mac OS X using GCC provided with the Apple SDK (which comes with XCode and such). However this is a PURE C program.

Some more hints of weird reactions. When I run sleep on the creation of the processes and check them directly I seem to be getting this:

3597 ttys000 0:00.00 ./mapreduce -m 3 -r 5 -i testindir -o testoutdir
3598 ttys000 0:00.00 (mapreduce)
3599 ttys000 0:00.00 ./mapreduce -m 3 -r 5 -i testindir -o testoutdir
3600 ttys000 0:00.00 ./mapreduce -m 3 -r 5 -i testindir -o testoutdir

Why are my last two processes looking good, while my first process doesn't look the same. What could this mean?

Edited by WingedPanther, 24 March 2009 - 11:20 AM.
Double post


#4
WingedPanther

WingedPanther

    A spammer's worst nightmare

  • Moderators
  • 16,831 posts
Unfortunately, programming with pipes/processes is not something I'm familiar with.
Programming is a branch of mathematics.
My CodeCall Blog | My Personal Blog

#5
redcameron

redcameron

    Newbie

  • Members
  • Pip
  • 3 posts
Ahhhh man, so screwed.