![]() |
|
![]() |
|
|
Thread Tools | Display Modes |
|
|
#1 |
|
Newbie
|
unix signal processing
The following is a program I'm trying to get working. My problem isn't the code itself. I can't seem to understand signal handling no matter what I read or try. Will someone please help me understand how to handle signals?
The following program spawns three processes which are passed as arguments. The program is suppose to initially spawn each process and then restart each of the processes (up to 4 times) when the SIGCHLD signal is received. Please note that the p1xxx variables aren't being used at the moment and I'm aware of this fact. I originally had this program working using the waitpid() and the WNOHANG option (no signal handling) and I was using the p1xxx variables as counters. #include <iostream>
#include <unistd.h>
#include <sys/wait.h>
using namespace std;
void sig_handler( int signo ); //signal handler
int spawnProcess(char *name); //spawns a particular process by name, returns PID
void syserr(const char *msg); //ignore this
int main(int argc, char * argv[]) {
if(argc != 4){
cerr << "Lab5: Program takes 3 processes as arguments" << endl;
//syserr("Program takes 3 arguments");
return 1;
}
//Initial spawn of our processes
int pids[3];
for(int i = 1; i < 4; i++){
pids[i-1] = spawnProcess(argv[i]);
}
//Keep track of how many times each process has been restarted
int p1Res=1, p2Res=1, p3Res=1;
struct sigaction act;
act.sa_handler = sig_handler;
sigemptyset( &act.sa_mask );
act.sa_flags = SA_NOCLDWAIT;
if( sigaction( SIGCHLD , &act, NULL ) == -1 ) {
perror( "sigaction" );
exit( 1 );
}
cout << "Parent has exited" << endl;
return 0;
}These are the functions void sig_handler( int signo ) {
}
//Spawn the process "name" and return its PID
int spawnProcess(char *name) {
int pid;
switch( (pid = vfork()) ){
case -1:
//syserr("vfork");
cerr << "Error calling vfork()" << endl;
return 1;
case 0:
if(execl(name, NULL) == -1){
//syserr("execl");
cerr << "Error calling execl" << endl;
return 1;
}
};
return pid;
}Thank you for your time. |
|
|
|
|
|
#2 |
|
Professional Programmer
Join Date: May 2006
Location: Maryland, USA
Posts: 306
Rep Power: 3
![]() |
Its late so you get no explanation but this. You set up the signal handler properly you just needed to actual check on the child processes in and start back up the right one. I use some global data so the signal handler would know what pids to check each time. You also need to sleep the parent so it can wait for the children. (sorry for mixed tabs and spaces, but I use spaces
)#include <iostream>
#include <string>
#include <unistd.h>
#include <sys/wait.h>
using namespace std;
// These need to be global so the signal handler can access them as well
int run_count[3] = {0, 0, 0};
int child_pids[3];
string processes[3];
void sig_handler( int signo ); //signal handler
int spawnProcess(const char *name); //spawns a particular process by name, returns PID
int main(int argc, char * argv[]) {
if(argc != 4){
cerr << "Lab5: Program takes 3 processes as arguments" << endl;
return 1;
}
// Setup the signal handler
struct sigaction act;
act.sa_handler = sig_handler;
sigemptyset( &act.sa_mask );
act.sa_flags = SA_NOCLDWAIT;
if( sigaction( SIGCHLD , &act, NULL ) == -1 ) {
perror( "sigaction" );
exit( 1 );
}
// Initial spawn of our processes
for(int i = 1; i < 4; i++){
processes[i-1] = string(argv[i]);
child_pids[i-1] = spawnProcess(argv[i]);
}
// Sleep for 20 seconds even if the timer is interupted by a signal
int sleep_time = 20;
while (0 != (sleep_time = sleep(sleep_time)))
{}
cout << "Parent has exited" << endl;
return 0;
}
void sig_handler( int signo ) {
int status;
for (int i = 0; i < 4; ++i)
{
// If we get negative one the child is dead
if ((-1 == waitpid(child_pids[i], &status, WNOHANG)) &&
(run_count[i] < 4))
{
// Increment the run count
run_count[i]++;
cout << "Restarting child '" << processes[i] << "' for the "
<< run_count[i] << " time" << endl;
// Run the process again and record its new pid, then
child_pids[i] = spawnProcess(processes[i].c_str());
}
}
}
//Spawn the process "name" and return its PID
int spawnProcess(const char *name) {
int pid;
switch( (pid = vfork()) ){
case -1:
cerr << "Error calling vfork()" << endl;
return 1;
case 0:
if(execl(name, NULL) == -1){
cerr << "Error calling execl" << endl;
return 1;
}
};
return pid;
}Oh yes, and there might be way to do this without global data. See the "wait" function in this page of the gnu c manual. |
|
|
|
|
|
#3 |
|
Newbie
|
Thanks for your reply. That code you posted is making my head hurt so I'll have to stare at it for awhile. The actual code you have in the sig_handler() looks similar to the code I had before this program used signals. I'm going to play with this for awhile longer. I'll post back if I have any more questions.
Once I understand this I'll probably try to change it so it doesn't use globals. I have a feeling that my professor will reject it if I use globals. |
|
|
|
|
|
#4 |
|
Professional Programmer
Join Date: May 2006
Location: Maryland, USA
Posts: 306
Rep Power: 3
![]() |
Using the GCC code I linked to you should be able to removed the need to store the pids globally but you somehow have to know what command to run when a certain child quits. The signal handler can't be passed any other information so it will be quite a trick for it to figure out what command it should run to "restart" a process.
|
|
|
|
|
|
#5 |
|
Newbie
|
It seems to be working just fine with the globals. There were some bugs but the logic of the code is sound. Why can't the signal handler be passed anything more than int signo? Is that just the way it's implemented?
Last edited by Ghosty; Dec 14th, 2006 at 1:15 PM. |
|
|
|
![]() |
| Bookmarks |
| Currently Active Users Viewing This Thread: 1 (0 members and 1 guests) | |
| Thread Tools | |
| Display Modes | |
|
|
Similar Threads
|
||||
| Thread | Thread Starter | Forum | Replies | Last Post |
| Unix commands compatible with Windows? | titaniumdecoy | Bash / Shell Scripting | 7 | Oct 5th, 2006 7:25 AM |
| Lions' Commentary on UNIX 6th Edition, with source code | Mad_guy | Book Reviews | 0 | Sep 24th, 2006 7:06 PM |
| Best Linux or Unix Desktop? | Prm753 | Coder's Corner Lounge | 23 | Apr 8th, 2006 10:17 AM |
| Need help coming up with mnemonic for command processing | aznluvsmc | Bash / Shell Scripting | 6 | Feb 21st, 2006 5:56 PM |
| Importing from DLL's on Unix | Kaja Fumei | Existing Project Development | 5 | Jan 9th, 2006 6:35 PM |