waitpid() non-blocking fork

This is a discussion on waitpid() non-blocking fork within the C Programming forums, part of the General Programming Boards category; I have a process that forks a child process that then runs a few syscalls. There is the possibility that ...

  1. #1
    Registered User
    Join Date
    Apr 2011
    Posts
    8

    waitpid() non-blocking fork

    I have a process that forks a child process that then runs a few syscalls. There is the possibility that the syscalls the child runs could cause it to block while it processes the calls, but I don't want the parent to wait. Further, I want the parent process to allow the child to run for a certain period of time and if the child is still blocked after a specified number of seconds, the parent will kill off the child.

    I am using waitpid(pid, &status, WNOHANG) to have the parent process not wait for the child. So I'm not sure what to do next. Do I keep looping back to waitpid() until either the child completes it's tasks and returns status or until the timeout value is reached or how do I loop over checking status of the child while evaluating the timeout?

    I looked over the waitpid man page but didn't see

  2. #2
    Captain Crash brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,159
    Quote Originally Posted by codevyper View Post
    I am using waitpid(pid, &status, WNOHANG) to have the parent process not wait for the child. So I'm not sure what to do next. Do I keep looping back to waitpid() until either the child completes it's tasks and returns status or until the timeout value is reached or how do I loop over checking status of the child while evaluating the timeout?

    I looked over the waitpid man page but didn't see
    Start the child. Do your other stuff for t seconds, where t is the timeout. Then call waitpid(..., NOHANG). If the child hasn't terminated yet, this will error, so use kill() to terminate the child and call waitpid() again to reap it.

    Note the intrinsic race condition here. If the child terminates AFTER you call waitpid() but BEFORE you call kill(), you'll be killing a non-existent process (no real problem), OR you might wind up killing a completely unrelated process that happens to have the same PID as the other process (unlikely, but possible, and bad if it happens). (EDIT: Nevermind the second possibility, it cannot happen)
    Last edited by brewbuck; 05-16-2011 at 08:36 PM.
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

  3. #3
    Registered User
    Join Date
    Nov 2004
    Location
    India
    Posts
    515
    You could do this using signals. Set up an alarm for the required timeout and in the handler function, reap the child or kill it.
    Code:
    >+++++++++[<++++++++>-]<.>+++++++[<++++>-]<+.+++++++..+++.[-]>++++++++[<++++>-] <.>+++++++++++[<++++++++>-]<-.--------.+++.------.--------.[-]>++++++++[<++++>- ]<+.[-]++++++++++.

  4. #4
    Registered User
    Join Date
    Apr 2011
    Posts
    8
    Okay, so as time permits I've been trying to get this going and I'm still kind of confused. Below is the parent portion of the forking code. The issue I'm having is that no matter what I do, when I specify WNOHANG in the waitpid function, it automatically returns a WIFEXITED status of 0. What I want it to do is continue iterating through the do/while loop until either the child exits with status, or waittime equals a predesignated timeout value and the parent hard kills the child.

    Right now, the do/while loop exits because waitpid passes a 0 to Stat as the result of specifying NOHANG.

    Code:
    else {
    	printf("The pid of the child is: %d\n", pid);
    	int waittime = 0;
    	int Stat;
    	do {
    		wpid = waitpid(pid, &Stat, WNOHANG);
    
    		if (WIFEXITED(Stat)) {
    			printf("Child exited, status=%d\n", WEXITSTATUS(Stat));
    			break;
    		}
    		else if (WIFSIGNALED(Stat)) {
    			printf("Child %d was terminated with a status of: %d \n", pid, WTERMSIG(Stat));
    			break;
    		}
    		else if (WIFSTOPPED(Stat)) {
    			printf("Child stopped (signal %d)\n", WSTOPSIG(Stat));
    			break;
    		}
    		else if (waittime < timeout){
    			printf("Parent waiting %d second(s).\n", waittime);
    			waittime ++;
    			sleep(1);
    		}
    		else {
    			printf("Killing child process\n");
    			kill(pid, SIGKILL);	
    		}
    	} while (!WIFEXITED(Stat) && !WIFSIGNALED(Stat));
    }

  5. #5
    and the hat of wrongness Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    32,337
    How about reading the manual?
    waitpid(2): wait for process to change state - Linux man page

    waitpid(): on success, returns the process ID of the child whose state has changed; on error, -1 is returned; if WNOHANG was specified and no child(ren) specified by pid has yet changed state, then 0 is returned.
    First you check wpid to see if a child actually exited, then you check Stat to find out why the child that was wpid actually exited.

    Otherwise you're just checking an uninitialised variable.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.
    I support http://www.ukip.org/ as the first necessary step to a free Europe.

  6. #6
    Registered User
    Join Date
    Apr 2011
    Posts
    8
    Thanks Salem,

    I try to do all the research before I post, but that line you quoted is towards the bottom of the page and I somehow missed it. Anyway, I have the code working now. For anyone else that may be interested, here's the working code:

    Code:
    else {
    	printf("The pid of the child is: %d\n", pid);
    	int waittime = 0;
    	int Stat;
    	do {
    		wpid = waitpid(pid, &Stat, WNOHANG);
    		if (wpid == 0) {
    			if (waittime < timeout) {
    				printf("Parent waiting %d second(s).\n", waittime);
    				sleep(1);
    				waittime ++;
    			}
    			else {
    				printf("Killing child process\n");
    				kill(pid, SIGKILL);	
    			}
    		}
    	} while (wpid == 0 && waittime <= timeout);
    
    	if (WIFEXITED(Stat)) {
    		printf("Child exited, status=%d\n", WEXITSTATUS(Stat));
    	}
    	else if (WIFSIGNALED(Stat)) {
    		printf("Child %d was terminated with a status of: %d \n", pid, WTERMSIG(Stat));
    	}
    }

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Help with non-blocking IO
    By soundstep in forum C Programming
    Replies: 4
    Last Post: 01-12-2011, 06:31 AM
  2. Non Blocking I/O
    By PetrolMan in forum C++ Programming
    Replies: 2
    Last Post: 04-03-2009, 08:47 PM
  3. help with waitpid()
    By kotoko in forum C Programming
    Replies: 1
    Last Post: 09-28-2008, 01:23 PM
  4. Pros and Cons of blocking versus non-blocking sockets?
    By abachler in forum Networking/Device Communication
    Replies: 4
    Last Post: 05-08-2008, 06:52 AM
  5. Non-Blocking IO
    By Unregistered in forum C++ Programming
    Replies: 1
    Last Post: 05-09-2002, 04:45 PM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21