![]() |
| | #1 |
| Registered User Join Date: Nov 2009
Posts: 9
| SIGNAL Suspended? 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);
}
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 | |
| | #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 | |
| | #3 |
| subminimalist 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);
__________________ Accuracy and integrity mean nothing if you don't make it past the censors...PYTHAGORAS |
| MK27 is offline | |
| | #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 | |
| | #5 |
| subminimalist Join Date: Jul 2008 Location: NYC
Posts: 3,944
| 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) Code: printf("P %d (%d)\n",i, x); fflush(stdout);
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();
__________________ 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 | |
| | #6 | |||||
| Registered User Join Date: Nov 2009
Posts: 9
| Quote:
Quote:
I added in this statement to the parent Code: x = waitpid(childPid, NULL, WUNTRACED); Quote:
Quote:
Quote:
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 | |
| | #7 | |
| subminimalist Join Date: Jul 2008 Location: NYC
Posts: 3,944
| 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:
__________________ 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 | |
| | #8 | ||
| Registered User Join Date: Nov 2009
Posts: 9
| Quote:
Quote:
With that said I am going to get my modified code in post it here. | ||
| Victor_November is offline | |
| | #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 | |
| | #10 | |
| subminimalist Join Date: Jul 2008 Location: NYC
Posts: 3,944
| Quote:
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 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 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);
__________________ Accuracy and integrity mean nothing if you don't make it past the censors...PYTHAGORAS | |
| MK27 is offline | |
| | #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 | |
| | #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 | |
![]() |
| Thread Tools | |
| Display Modes | |
|
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 |