Thread: SIGNAL Suspended?

  1. #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

  2. #2
    Jack of many languages Dino's Avatar
    Join Date
    Nov 2007
    Location
    Chappell Hill, Texas
    Posts
    2,332
    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.
    Mainframe assembler programmer by trade. C coder when I can.

  3. #3
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    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.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  4. #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.

  5. #5
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    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.
    Last edited by MK27; 11-07-2009 at 05:39 PM.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  6. #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

    "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.


    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.


    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.


    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.

  7. #7
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    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...
    Last edited by MK27; 11-07-2009 at 07:30 PM.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  8. #8
    Registered User
    Join Date
    Nov 2009
    Posts
    9
    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.

    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.

  9. #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);
    }

  10. #10
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    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.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  11. #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.

  12. #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);
    }

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 3
    Last Post: 07-07-2009, 10:05 AM
  2. Replies: 3
    Last Post: 10-15-2008, 09:24 AM
  3. Signal and exception handling
    By nts in forum C++ Programming
    Replies: 23
    Last Post: 11-15-2007, 02:36 PM
  4. NAQ: Everything you never wanted to know about CPP
    By evildave in forum C Programming
    Replies: 21
    Last Post: 12-12-2005, 10:56 AM
  5. signal handling
    By trekker in forum C Programming
    Replies: 2
    Last Post: 07-05-2002, 02:52 AM