Hi guys,
For some reason my application is doing a seg fault when I tell the parent to wait for the child to be done with the process.
Here is the output:
andorian 73% pr5 -a 3 -s 10 -c 1
child_alarm_time = 3
child_processes = 1
child_sleep_time = 10
Installed SIGALRM, SIGINIT,SIGCHLD signals
18740: Tue Oct 14 02:57:45 2008 alarm signal received
18740: Tue Oct 14 02:57:48 2008 alarm signal received
18740: Tue Oct 14 02:57:51 2008 alarm signal received
18740: Tue Oct 14 02:57:52 2008 here is child 0
18740: Tue Oct 14 02:57:52 2008 Killing this child process. 0
18739: Tue Oct 14 02:57:52 2008 child signal received - ignored
Segmentation fault
I also get the seg fault if I do the following:
pr5 -c 1
pr5 -c 2
Here is my code
Code:
static void Sleep(int alarm_time_interval, int total_sleep_time)
{
int remaining_sleep_time = total_sleep_time;
while (remaining_sleep_time > 0)
{
if (alarm_time_interval > 0)
{ alarm(alarm_time_interval); }
remaining_sleep_time = sleep(remaining_sleep_time);
}
}
/*----------------------------------------------------------------------------*/
/* The functions in this section are intended to demonstrate various usages and
* properties of signals and signal handlers. They should be removed or modified
* in the final version of the program.
*/
static void generic_signal_handler(int sig)
{
print_message_1("generic_signal_handler, signal", sig);
}
static void SIGALRM_handler(int sig)
{
if (sig == SIGALRM)
{ print_message("alarm signal received"); }
else
{ print_message_1("serious error: SIGALRM_handler, received signal", sig); }
}
static void SIGINT_handler(int sig)
{
if (sig == SIGINT)
{ print_message("interrupt signal received - ignored"); }
else
{ print_message_1("serious error: SIGINT_handler, received signal", sig); }
}
static void SIGCHLD_hanlder(int sig)
{
if(sig == SIGCHLD)
{ print_message("child signal received - ignored"); }
else
{ print_message_1("serious error: SIGCHLD_handler, received signal", sig); }
}
#ifndef NSIG
#define NSIG 64
#endif
static int generic_signal_handler_installed[NSIG];
/* signal 0 is reserved
* the default handlers for SIGKILL and SIGSTOP cannot be replaced
*/
/* try to replace every default signal handler */
static void signal_setup(void)
{
/* int i, ret;
for (i = 0; i < NSIG; i++)
{
ret = install_signal_handler(i, generic_signal_handler);
generic_signal_handler_installed[i] = (ret == 0);
}*/
printf("Installed SIGALRM, SIGINIT,SIGCHLD signals\n");
//just set up these 3 signal handlers
install_signal_handler(SIGALRM, SIGALRM_handler);
install_signal_handler(SIGINT, SIGINT_handler);
install_signal_handler(SIGCHLD,SIGCHLD_hanlder);
}
/*----------------------------------------------------------------------------*/
int main(int argc, char *argv[])
{
//set up the signal handlers
signal_setup();
//check to see if no arguments were passed, if there weren't then don't
//create any children
//fork children based on what is passed through the command line
pid_t child_pid;
//holds an array of the child processes so the parent can wait for them.
pid_t child_array[MAX_CHILDREN];
int CHILD_STAT;
//print_process_table("Table before forking.");
//creating processes
for(int i =0; i < child_processes; i++)
{
child_pid = fork();
child_array[i] = child_pid;
if(child_pid == (pid_t)(-1))
{
//this is the parent process. The fork failed, and there is no child
print_message_error("fork()", strerror(errno));
exit(EXIT_FAILURE);
}
else if(child_pid == 0)
{
//this is a child process. The fork worked
//checking to see if alarm/sleep flags were set
if(a_flag || s_flag)
{
Sleep(child_alarm_time,child_sleep_time);
}
print_message_1("here is child ",i);
print_message_1("Killing this child process.",i);
exit(child_exit_status);
}
else
{
//print_message("here is the parent, all children created.");
//if this flag is set, then set the parent alarm/sleep
if(b_flag || t_flag)
{
//set alarm
//printf("set the alarm: %d set sleep: %d for the process: %d\n",parent_alarm_time,parent_sleep_time,getpid());
Sleep(parent_alarm_time,parent_sleep_time);
}
//this is a parent process. The fork worked
//add more code but do not exit yet
//Wait for the child process to be done
wait_child(child_pid,CHILD_STAT);
//update the process table
//printf("added child process %d\n", child_pid);
insert_process_table(child_pid);
//print_process_table("Table after inserting the process in parent.");
//print_process_table("Parent calling this again");
}
}
//tried this didn't work
/*for(int i = 0; i < child_processes; i++)
{
wait_child(child_array[i],CHILD_STAT);
}*/
print_message("here is the parent, all children created");
if(b_flag || t_flag)
{
//set alarm
//printf("set the alarm: %d set sleep: %d for the process: %d",parent_alarm_time,parent_sleep_time,getpid());
Sleep(parent_alarm_time,parent_sleep_time);
}
return EXIT_SUCCESS;
So basically I'm getting this when I try to create a 1 or more child processes and I tell the parent to wait for the child to be done, so the wait_child is where the error has to be at and I"m not sure why.
My guess is that I'm killing the process and then asking it to wait for a dead process?
Here is what the child_wait process looks like:
Code:
#include <errno.h>
/* for waitpid(2) and wait(2) */
#include <sys/types.h>
#include <sys/wait.h>
#include "pr5_wait.h"
/*----------------------------------------------------------------------------*/
/* wait for a child process whose pid you know
*
* return 1 if a child was found
* *child_status has been updated, and the child has terminated
*
* return 0 if no child was found
* *child_status has not been updated
*/
int wait_child(pid_t wait_pid, int *child_status)
{
int s;
/* loop because waitpid() can be interrupted by a signal and return early */
while (waitpid(wait_pid, &s, 0) == (pid_t)(-1))
{
if (errno == ECHILD) /* no more children */
{ return 0; }
}
*child_status = s;
return 1;
}
/*----------------------------------------------------------------------------*/
/* wait for a child process whose pid you do not know
* if more than one child has terminated, report only one
*
* return 1 if a child was found
* *wait_pid and *child_status have been updated, and the child has terminated
*
* return 0 if no child was found
* *wait_pid and *child_status have not been updated
*/
int wait_any_child(pid_t *wait_pid, int *child_status)
{
pid_t w;
int s;
/* loop because wait() can be interrupted by a signal and return early */
while ((w = wait(&s)) == (pid_t)(-1))
{
if (errno == ECHILD) /* no more children */
{ return 0; }
}
*wait_pid = w;
*child_status = s;
return 1;
}
/*----------------------------------------------------------------------------*/
That code is correct, I"m just using it wrong I think.
Any help would be great.