C Board  

Go Back   C Board > General Programming Boards > C Programming

Reply
 
LinkBack Thread Tools Display Modes
Old 11-07-2009, 03:38 PM   #1
Registered User
 
Join Date: Nov 2009
Posts: 9
SIGNAL Suspended?

Hi,

First off I am doing homework. I have been looking at this site to view code examples, and I am happy to see the technical caliber on these forums. This is the first time I am programming with signals and I must say that I am "familiar" at best when coding with them.

My assignment is to sync a parent and a child using signals. I have got that to work (sort of). But the output is quite strange. Anyhow, if anyone can tell me if I am using signals right, and if anyone could explain why I am getting this crazy output, would be awesome.

Thanks!

code file w8.c:

Code:
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <sys/wait.h>

void mySignalHandler(int sig);
void sigParent(void);
void sigChild(void);
int wait_status;
pid_t parentPid, childPid, pid;

int main()
{
	int i;
	wait_status = 1; 
	pid  = fork();
	switch(pid)
		{
		case -1: /* an error occurred */
		printf("Fork error\n");
		break;

		case 0: /* this code is executed by the child process */
		childPid = getpid();
		signal(SIGCONT, mySignalHandler);
		signal(SIGSTOP, mySignalHandler);
			for(i=1; i<10; i++)
			{
				if(wait_status == 0)
				{
				waitpid(parentPid, NULL, WUNTRACED);
				}
				else
				{
				printf("Child process, iteration: %d\n", i);
				sigParent();
				}
			}
		break;

		default: /* this code is executed by the parent process */
		parentPid = getpid();
		signal(SIGCONT, mySignalHandler);
		signal(SIGSTOP, mySignalHandler);
			for(i=1; i<10; i++)
			{
				if(wait_status == 0)
				{
				waitpid(childPid, NULL, WUNTRACED);
				}
				else
				{
				printf("Parent process, iteration: %d\n", i);
				sigChild();
				}
			}/*end for*/
		break;
		
		} /*end switch*/
}/*end main*/

void mySignalHandler(int sig)
{
	if(sig == SIGSTOP)
		wait_status = 0;
	else if(sig == SIGCONT)
		wait_status = 1;

}

void sigParent(void)
{	
	kill(parentPid, SIGCONT);
	raise(SIGSTOP);
}
void sigChild(void)
{
	kill(childPid, SIGCONT);
	raise(SIGSTOP);
}
and then the output looks like this. Its not always the same either. But it does always say signal suspended:

Code:
Parent process, iteration: 1

Child process, iteration: 1
Parent process, iteration: 2
Child process, iteration: 2
Parent process, iteration: 3
Child process, iteration: 3
Parent process, iteration: 4
Child process, iteration: 4
Parent process, iteration: 5
Suspended (signal)
Child process, iteration: 5
Parent process, iteration: 6
Child process, iteration: 6
Parent process, iteration: 7
Child process, iteration: 7
Parent process, iteration: 8
Child process, iteration: 8
Parent process, iteration: 9
Child process, iteration: 9
[8]  + Suspended (signal)            ./a.out
Victor_November is offline   Reply With Quote
Old 11-07-2009, 03:54 PM   #2
Jack of many languages
 
Join Date: Nov 2007
Location: Katy, Texas
Posts: 1,929
The last time anyone used caliber to describe my skills was back in high school when I tried out for the Tennis team. After my try out, the coach came up to me, thanked me for trying out, and then said he didn't need anyone of my caliber on his team at the moment.
__________________
Mac and Windows cross platform programmer. Ruby lover.

Memorable Quotes From Recent Posts:

I can't remember.
Dino is offline   Reply With Quote
Old 11-07-2009, 04:27 PM   #3
subminimalist
 
MK27's Avatar
 
Join Date: Jul 2008
Location: NYC
Posts: 3,944
You should check the return value of waitpid. What happens with this is that as soon as waitpid() occurs in the child, it returns an error immediately because parentPid is not it's child. It does not wait for anything or perform any purpose.

And as soon as it occurs in the parent, the parent must wait until the child has completed it's 10 iterations and terminated.

You should be aware that unless you use this after your printf statements:
Code:
fflush(stdout);
your output may not reflect the real order of events.
__________________

Accuracy and integrity mean nothing if you don't make it past the censors...PYTHAGORAS
MK27 is offline   Reply With Quote
Old 11-07-2009, 04:54 PM   #4
Registered User
 
Join Date: Nov 2009
Posts: 9
I took out if logic and the wait statement from the child. I also added the flush functions after the printf's. The output still looks the same.

Did the use of the signals seem correct? They remind of something like a try-catch in Java.
Victor_November is offline   Reply With Quote
Old 11-07-2009, 05:36 PM   #5
subminimalist
 
MK27's Avatar
 
Join Date: Jul 2008
Location: NYC
Posts: 3,944
Quote:
Originally Posted by Victor_November View Post
IThe output still looks the same.
I'm not sure what you are trying to accomplish. I get different output than what you report, so if you are going for a consistent effect, you are not getting it. Eg:
Code:
C 1 (0)
Child process, iteration: 1
C 2 (0)
C 3 (0)
C 4 (0)
C 5 (0)
C 6 (0)
C 7 (0)
C 8 (0)
C 9 (0)
P 1 (0)
Parent process, iteration: 1
P 2 (0)
P 3 (0)
P 4 (0)
P 5 (0)
P 6 (0)
P 7 (0)
P 8 (0)
P 9 (0)
The "P" & "C" lines I added in to track the iterations:
Code:
printf("P %d (%d)\n",i, x); fflush(stdout);
"x" was the return value from waitpid, but I removed that too.

As you can see, not much happens. parentPid remains UNDEFINED as it does in your previously posted code, so of course the parent never receives any signal, and by the time the parent loops, the child has finished and exited also so there is no signal for it.

The plain truth is there is absolutely no way you can rely on two seperate processes performing a simple for loop in a synchronized manner, as you may have presupposed, without 1) a specific time delay, or 2) some IPC such as signal handling. The code you posted does not really do the later, altho it may appear to in some sense.

Perhaps the output you posted is from some different code? Anyway, without an actual value for parentPid, you've got nothing substantial going on. This line:
Code:
parentPid = getpid();
is presumably in the wrong place. Forked children DO NOT share variables as with threading. If you print the value of "parentPid" in the child process, you will see it is meaningless, and different from it's value in the parent, where it is set AFTER the fork.
__________________

Accuracy and integrity mean nothing if you don't make it past the censors...PYTHAGORAS

Last edited by MK27; 11-07-2009 at 05:39 PM.
MK27 is offline   Reply With Quote
Old 11-07-2009, 06:17 PM   #6
Registered User
 
Join Date: Nov 2009
Posts: 9
Quote:
Originally Posted by MK27 View Post
I'm not sure what you are trying to accomplish. I get different output than what you report, so if you are going for a consistent effect, you are not getting it.
I am trying to fork a process then using two for loops have them alternate by printing a sequences of iterations

Quote:
"x" was the return value from waitpid, but I removed that too.

I added in this statement to the parent

Code:
x = waitpid(childPid, NULL, WUNTRACED);
I print it after the printf stating the iteration number.


Quote:
As you can see, not much happens. parentPid remains UNDEFINED as it does in your previously posted code, so of course the parent never receives any signal, and by the time the parent loops, the child has finished and exited also so there is no signal for it.
I am getting a value for parentPid. See output below.


Quote:
The plain truth is there is absolutely no way you can rely on two seperate processes performing a simple for loop in a synchronized manner, as you may have presupposed, without 1) a specific time delay, or 2) some IPC such as signal handling. The code you posted does not really do the later, altho it may appear to in some sense.
I am trying to use signals to achieve this effect. I take it though from your answer that I am not using them correctly.


Quote:
Perhaps the output you posted is from some different code?

I know I sound new, and its true I am pretty much a noob; but, not that new.

OK here is the new output:
The pid: 4 is the value of x set by waitpid. As far as our outputs are concerned, I think it has to do with the fact that I am logged remotely to a university server(?). It is Solaris. I mean: perhaps it is machine differences?

Code:
Parent process, iteration: 1 pid: 4
Parent pid: 9537

Child process, iteration: 1
Suspended (signal)
Parent process, iteration: 2 pid: 4
Parent pid: 9537
Child process, iteration: 2
Parent process, iteration: 3 pid: 4
Parent pid: 9537
Child process, iteration: 3
Parent process, iteration: 4 pid: 4
Parent pid: 9537
Child process, iteration: 4
Parent process, iteration: 5 pid: 4
Parent pid: 9537
Child process, iteration: 5
Parent process, iteration: 6 pid: 4
Parent pid: 9537
[1]  + Suspended (signal)            ./a.out
Child process, iteration: 6
Parent process, iteration: 7 pid: 4
Parent pid: 9537
Child process, iteration: 7
Parent process, iteration: 8 pid: 4
Parent pid: 9537
Child process, iteration: 8
Parent process, iteration: 9 pid: 4
Parent pid: 9537
Child process, iteration: 9

Last edited by Victor_November; 11-07-2009 at 06:53 PM.
Victor_November is offline   Reply With Quote
Old 11-07-2009, 07:21 PM   #7
subminimalist
 
MK27's Avatar
 
Join Date: Jul 2008
Location: NYC
Posts: 3,944
Quote:
Originally Posted by Victor_November View Post
I am getting a value for parentPid. See output below.
Sure. But the code you have actually posted in this thread would only do that by chance -- if it gets set in the "default" clause of the switch routine BEFORE the case(0) is executed. If, by chance, this is what happens on your machine with your compiler, that does not mean that your code is properly written. It means you are getting lucky. That is very normal. At this stage, just getting something to work for you is hard enough, so if something works, you consider it "error-free".

But that is not the case. As I said, I am not nearly getting your output.

Proper code works consistently, not occasionally only in a few places. The real mistakes you make that cause a real error for you are obvious -- but an error or bug is not something that must happen, it is something that can. So of course it is totally normal, again, that you will have bugs in your code based on fortuitous circumstances (particular to your box/compiler) if you decide "works for me" is good enough. There are all kinds of undefined behavior that MAY work -- that does not mean they are correct or reliable.

I could move the getpid() line to a place before the fork, etc, and get this program to execute "better". But then I would no longer be talking about the same program, and I would be ignoring a significant mistake. Even if I did that, there would be no point in trying to analyse further problems, or try and help you get it right, since it is already wrong.

Put the getpid() in a more LOGICAL place and post all the code as it is now.

Vis, the return value of waitpid:
Quote:
Originally Posted by POSIX standard
If wait() or waitpid() returns because the status of a child process is available, these functions shall return a value equal to the process ID of the child process for which status is reported. If wait() or waitpid() returns due to the delivery of a signal to the calling process, -1 shall be returned and errno set to [EINTR]. If waitpid() was invoked with WNOHANG set in options, it has at least one child process specified by pid for which status is not available, and status is not available for any process specified by pid, 0 is returned. Otherwise, (pid_t)-1 shall be returned, and errno set to indicate the error.
Linux and I believe Solaris both conform to POSIX, so it is hard to see how "4" is an indication of success here...
__________________

Accuracy and integrity mean nothing if you don't make it past the censors...PYTHAGORAS

Last edited by MK27; 11-07-2009 at 07:30 PM.
MK27 is offline   Reply With Quote
Old 11-07-2009, 07:52 PM   #8
Registered User
 
Join Date: Nov 2009
Posts: 9
Quote:
At this stage, just getting something to work for you is hard enough, so if something works, you consider it "error-free".
I can assure you that this is not the case.

Quote:
Linux and I believe Solaris both conform to POSIX, so it is hard to see how "4" is an indication of success here...
I am not claiming success. Perhaps I did not make myself clear enough the first time: I am really new at this stuff. MK27 I am not trying to accuse of being wrong; quite the contrary in fact. I am trying to explain to you what I am seeing, and I was just curious why our outputs are different especially if we both have POSIX complaint machines.

With that said I am going to get my modified code in post it here.
Victor_November is offline   Reply With Quote
Old 11-07-2009, 07:58 PM   #9
Registered User
 
Join Date: Nov 2009
Posts: 9
new code

Hopefully this is more readable. I moved the getpid() above the fork.

Code:
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <sys/wait.h>

void mySignalHandler(int sig);
void sigParent(void);
void sigChild(void);
int wait_status;
pid_t parentPid, childPid, pid;

int main()
{
	int i,x;
	wait_status = 1;
	parentPid = getpid();
	pid  = fork();
	switch(pid)
		{
		case -1: /* an error occurred */
		printf("Fork error\n");
		break;

		case 0: /* this code is executed by the child process */

			childPid = getpid();

			signal(SIGCONT, mySignalHandler);
			signal(SIGSTOP, mySignalHandler);

			for(i=1; i<10; i++)
			{
				printf("Child process, iteration: %d\n", i);
				fflush(stdout);
				sigParent();
			}
		break;

		default: /* this code is executed by the parent process */
	
			signal(SIGCONT, mySignalHandler);
			signal(SIGSTOP, mySignalHandler);

			for(i=1; i<10; i++)
			{
				if(wait_status == 0)
				{
				x = waitpid(childPid, NULL, WUNTRACED);
				}
				else
				{
				printf("Parent process, iteration: %d pid: %d\n", i, x);
				printf("Parent pid: %d\n", parentPid);
				fflush(stdout);
				sigChild();
				}
			}/*end for*/
		break;
		
		} /*end switch*/
}/*end main*/

void mySignalHandler(int sig)
{
	if(sig == SIGSTOP)
		wait_status = 0;
	else if(sig == SIGCONT)
		wait_status = 1;

}

void sigParent(void)
{	
	kill(parentPid, SIGCONT);
	raise(SIGSTOP);
}
void sigChild(void)
{
	kill(childPid, SIGCONT);
	raise(SIGSTOP);
}
Victor_November is offline   Reply With Quote
Old 11-07-2009, 10:29 PM   #10
subminimalist
 
MK27's Avatar
 
Join Date: Jul 2008
Location: NYC
Posts: 3,944
Quote:
Originally Posted by Victor_November View Post
Hopefully this is more readable. I moved the getpid() above the fork.
Okay, well it seems to work much more along the lines of what I think you wanted now. One of two possibilities:

Code:
[root~/C] ./a.out
Child process, iteration: 1
Parent process, iteration: 1 pid: 0
Parent pid: 6754
Child process, iteration: 2

[1]+  Stopped                 ./a.out
and hooray,
Code:
[root~/C] ./a.out
Parent process, iteration: 1 pid: 0
Parent pid: 6760

[1]+  Stopped                 ./a.out
[root~/C] Child process, iteration: 1
Parent process, iteration: 2 pid: 0
Parent pid: 6760
Child process, iteration: 2
Parent process, iteration: 3 pid: 0
Parent pid: 6760
Child process, iteration: 3
Parent process, iteration: 4 pid: 0
Parent pid: 6760
Child process, iteration: 4
Parent process, iteration: 5 pid: 0
Parent pid: 6760
Child process, iteration: 5
Parent process, iteration: 6 pid: 0
Parent pid: 6760
Child process, iteration: 6
Parent process, iteration: 7 pid: 0
Parent pid: 6760
Child process, iteration: 7
Parent process, iteration: 8 pid: 0
Parent pid: 6760
Child process, iteration: 8
Parent process, iteration: 9 pid: 0
Parent pid: 6760
Child process, iteration: 9

[1]+  Done                    ./a.out
altho the 1st one is slightly more likely. This is a race condition.

I ran it with gdb, which is kind of handy because it pauses for signals and allows you to "continue". But the "continue" in gdb will continue thru a SIGSTOP, and what is noticable is that sometimes the cards fall so that both processes have just received SIGSTOP but no SIGCONT.

If you add this at line 36, right after "sigParent()":
Code:
sleep(1);
the program runs consistantly inside and outside gdb.
__________________

Accuracy and integrity mean nothing if you don't make it past the censors...PYTHAGORAS
MK27 is offline   Reply With Quote
Old 11-07-2009, 10:58 PM   #11
Registered User
 
Join Date: Nov 2009
Posts: 9
Thanks for looking at it for me. As a part of the assignment I can't use sleep. But I will keep plugging away at it.
Victor_November is offline   Reply With Quote
Old 11-10-2009, 11:55 PM   #12
Registered User
 
Join Date: Nov 2009
Posts: 9
Here is some updated code:


It works but I still get a Signal Suspended message at a random (or so it appears) place in the output.

Code:
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <sys/wait.h>

void sigParent(void);
void sigChild(void);
int wait_status;
pid_t parentPid, childPid, pid;

int main()
{
	int i;
	wait_status = 1;
	parentPid = getpid();
	pid  = fork();
	switch(pid)
		{
		case -1: /* an error occurred */
		printf("Fork error\n");
		break;

		case 0: 	/* this code is executed by the child process */

			childPid = getpid();

			signal(SIGCONT, SIG_DFL);
			signal(SIGSTOP, SIG_DFL);

			for(i=1; i<10; i++)
			{
				printf("Child process, iteration: %d\n", i);
				fflush(stdout);
				sigParent();
			}
		break;

		default: 	/* this code is executed by the parent process */
			
			waitpid(childPid,NULL, WUNTRACED);
			signal(SIGCONT, SIG_DFL);
			signal(SIGSTOP, SIG_DFL);

			for(i=1; i<10; i++)
			{
				printf("Parent process, iteration: %d\n", i);
				fflush(stdout);
				sigChild();
			}/*end for*/
		break;
		
		} /*end switch*/
}/*end main*/



void sigParent(void)
{	
	kill(parentPid, SIGCONT);
	raise(SIGSTOP);
}
void sigChild(void)
{
	kill(childPid, SIGCONT);
	raise(SIGSTOP);
}
Victor_November is offline   Reply With Quote
Reply

Thread Tools
Display Modes

Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
sigaction - how to find and invoke previous signal handler (sa_handler) j1mw3b Linux Programming 3 07-07-2009 10:05 AM
How can you make a parent process wait for a child? I'm gettin a seg fault. mr_coffee C Programming 3 10-15-2008 09:24 AM
Signal and exception handling nts C++ Programming 23 11-15-2007 02:36 PM
NAQ: Everything you never wanted to know about CPP evildave C Programming 21 12-12-2005 10:56 AM
signal handling trekker C Programming 2 07-05-2002 02:52 AM


All times are GMT -6. The time now is 07:50 PM.


Powered by vBulletin® Version 3.8.1
Copyright ©2000 - 2009, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO 3.3.0 RC2

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