[SOLVED] Sequencing problem with raising a signal method
ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
I am encountering with a problem here and any help would be very much appreciated.
I was trying to program using fork(). The objective of this code is to
1. I am activating a process A - SubSuctionMotors.
2. Process A is going to stop with either of this condition
a) Switch is activated - swret=1
b) Time allowed has expired
3. Stop the process A.
*Process A is running a motor.
Now, let's see the code.
Code:
void usrl_handler( int sig_num )
{
printf( "Time out(%d), signal received to terminate motor\n", getpid() );
SubSuctionMotors (0);
}
int SubFrameVertical ()
{
int swret;
int rc=0;
int timeOut=0;
pid_t ret;
int role=-1;
ret = fork();
if (ret>0) { /*Parent Context*/
printf( "Parent: This is the parent process (pid %d)\n", getpid() );
SubSuctionMotors (1); /*Motor is activated and running.*/
signal ( SIGUSR1, usrl_handler );
role = 0;
swret=CheckSwitch(0); /*Command to check if switch is activated.*/
while(swret==0)
{
swret=CheckSwitch(0); /*while loop to continuously check if switch is activated, loop will exit if switch is activated (swret=1).*/
}
SubSuctionMotors (0); /*Stop motor running.*/
}
else if (ret == 0) { /*Child Context*/
printf( "Child: This is the child process (pid %d)\n", getpid() );
role = 1;
sleep ( 2 ); /*Start counting time when motor start running, after 2 second, motor should be stopped. This is an additional condition that we add in case the switch did not being activated to protect our application.*/
printf( "Child: Time Out, Sending SIGUSR1 to pid%d\n", getppid() );
kill( getppid(), SIGUSR1 );
}
SubSuctionMotors (0);
return rc;
}
We tried to compile the code and run it.
Now, our problem is
1. We purposely force the switch to be inactive to test the child process (timer), whether after 2 seconds the motor stop. It turns out to be successful in first few attempts. After some while, the program hang, nothing is executed anymore and the program is not exit or terminated. What can cause the program to hang?
2. We tried to stop motor by switch activation (if the switch is to be successfully activated, the time it takes will always be shorter than the timer allowed time). However, the program did not seems like noticing the switch has been activated, and it just stop the motor according to timer. Why it behave this way?
We purposely force the switch to be inactive to test the child process (timer), whether after 2 seconds the motor stop. It turns out to be successful in first few attempts. After some while, the program hang, nothing is executed anymore and the program is not exit or terminated. What can cause the program to hang?
It isn't clear how the parent task is meant to terminate if the switch is forced to be inactive? It receives the signal, but doesn't do anything with it.
Quote:
We tried to stop motor by switch activation (if the switch is to be successfully activated, the time it takes will always be shorter than the timer allowed time). However, the program did not seems like noticing the switch has been activated, and it just stop the motor according to timer. Why it behave this way?
Possibly the parent task had already exited. Have you tested that the CheckSwitch code works as you expect?
It is also not a good idea to have a busy loop (the check switch loop) that contains no waits or delays. At least add in a small sleep (eg a few milliseconds, or whatever is appropriate given the effect of the motor).
You also need to be careful about calling printf (and anything else that would make a system call) inside an interrupt handler. Most of these are unsafe (meaning that there is the risk of crashes or worse).
The easiest method is for the interrupt hander to just set a flag variable, which the main loop can monitor and exit normally (stopping the motor as it does so).
Last edited by neonsignal; 03-05-2010 at 04:25 AM.
It isn't clear how the parent task is meant to terminate if the switch is forced to be inactive? It receives the signal, but doesn't do anything with it.
What we actually want the sequence to be is as following:
a) motor start running with function SubSuctionMotors(1)
b) switch signal is read continuously with the loop while (swret==0),when the switch is activated, swret=1, and exit the loop. Motor is then stop by SubSuctionMotors(0) and also exit parent process.
c) child process start at the same time when motor start to run. It start to count time with sleep(2). In this interval of time, if no switch activation is detected, when 2 seconds is over, function SubSuctionMotors(0) in the child process is used to stop motor from running any more. Child process exit and send signal to parent to tell parent to exit also.
Did our code right for this sequence?
Quote:
Have you tested that the CheckSwitch code works as you expect?
The CheckSwitch code is definitely works, we tried it out before many times and all works just well.
Quote:
The easiest method is for the interrupt hander to just set a flag variable, which the main loop can monitor and exit normally (stopping the motor as it does so).
Child process exit and send signal to parent to tell parent to exit also.
A signal does not abort a process unless you do it explicitly. This might be confusing at first, because unhandled signals default to abort; however, if you handle the signal, then all it does is run the signal handler function.
This means that no matter which of your processes finishes first, the other will be left running (which may lead to some confusion).
Quote:
Main loop in this case means?
By main loop I mean the switch testing loop in the parent thread.
Incidentally, what does the check switch code look like?
I just found out the solution to exit the child process as well as the parent process. It is all to be coded in handler function.
This is my code. I hope my code is stable (not hiding any risk of crash or buffer overflow).
Code:
void usrl_handler( int sig_num )
{
printf( "Time out(%d), signal received to terminate motor\n", getpid() );
SubSuctionMotors (0);
exit(0);
}
int SubFrameVertical (int updown)
{
int dir;
int swret;
pid_t ret;
int role=-1;
ret = fork();
if (ret>0) { /*Parent Context*/
printf( "Parent: This is the parent process (pid %d)\n", getpid() );
SubSuctionMotors (1);
signal ( SIGUSR1, usrl_handler );
role = 0;
if (returnresult >0) SendStatus();
else printf("Connection Fail\n");
swret=CheckSwitch(0);
while(swret==0)
{
swret=CheckSwitch(0);
}
SubSuctionMotors (0);
}
else if (ret == 0) { /*Child Context*/
printf( "Child: This is the child process (pid %d)\n", getpid() );
role = 1;
sleep ( 2 );
printf( "Child: Time Out, Sending SIGUSR1 to pid%d\n", getppid() );
kill( getppid(), SIGUSR1 );
}
SubSuctionMotors (0);
if (returnresult >0) SendStatus();
else printf("Connection Fail\n");
return rc;
}
I have add in "exit(0)" in the usrl_handler. This settled my problem and get my sequence right.
However, I think I still encountering with problem of running out of memory after executing this the child code for a few times (this means switch is never being activated and child process--time out take turn to stop motor). Someone suggested that I should just pause the program when time out happen and wait for instruction from user. I am currently studying this problem. Any help or idea will be very welcomed and appreciated.
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.