- #1
freshcoast
- 185
- 1
Hello,
1. Homework Statement
I am to implement a program where the parent process creates three child processes each running their own specific code, child 1 will be running a wallclock, child 2 will be a file manager and child 3 will be the countdown timer and is also the signaler. Child 1 is a basic wallClock which just outputs the current local time in military format. Child 2 is a file manager, therefore it creates it's own child process to run the exec command on the file "/usr/bin/uptime" and handles it's return to execute every 5 seconds or until it has been signaled. Child 3 is a basic countdown timer which upon reaching 00:00 it will signal the sibling processes to terminate.
So far my implementation of the features have been correct, my only issue is with the runFile child. The output(given below the code) shows that when the countdown child process is done, it successfully signals the wallClock process to exit which it does successfully. However, after both child processes has closed, the runFile child is lingering for a couple more runs until it eventually receives the signal later. My question is why is that?, I don't get how it receives the signal MUCH later, because obviously the pipes are working because it eventually gets the signal and successfully terminates it self, so I don't understand why it receives the signal at a later time?
1. Homework Statement
I am to implement a program where the parent process creates three child processes each running their own specific code, child 1 will be running a wallclock, child 2 will be a file manager and child 3 will be the countdown timer and is also the signaler. Child 1 is a basic wallClock which just outputs the current local time in military format. Child 2 is a file manager, therefore it creates it's own child process to run the exec command on the file "/usr/bin/uptime" and handles it's return to execute every 5 seconds or until it has been signaled. Child 3 is a basic countdown timer which upon reaching 00:00 it will signal the sibling processes to terminate.
The Attempt at a Solution
So far my implementation of the features have been correct, my only issue is with the runFile child. The output(given below the code) shows that when the countdown child process is done, it successfully signals the wallClock process to exit which it does successfully. However, after both child processes has closed, the runFile child is lingering for a couple more runs until it eventually receives the signal later. My question is why is that?, I don't get how it receives the signal MUCH later, because obviously the pipes are working because it eventually gets the signal and successfully terminates it self, so I don't understand why it receives the signal at a later time?
Code:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <time.h>
#define DEFAULT 10
#define pipeSize 2
#define NUMBEROFCHILD 3
#define STOP 1
#define RUN 0
int fd[pipeSize];
int fd2[pipeSize];
void wallClock(){
int status = RUN; /*signals*/
int newStatus = RUN;
time_t now;
struct tm *lcltime;
if(close(fd[1]) == -1){
printf("Error closing writing end of pipe in wallClock\n");
_exit(EXIT_FAILURE);
}
if(close(fd2[0]) == -1){ /*close unused pipes*/
printf("Error closing reading end of pipe2 in wallClock\n");
_exit(EXIT_FAILURE);
}
if(close(fd2[1]) == -1){
printf("Error closing writing end of pipe2 in wallClock\n");
_exit(EXIT_FAILURE);
}
while(status != STOP){ /*loop until signal occurs*/
now = time(NULL);
lcltime = localtime(&now);
printf("the time is %d:%d:%d\n", lcltime->tm_hour,lcltime->tm_min,lcltime->tm_sec);
sleep(1);
read(fd[0], &newStatus, sizeof(newStatus)); /*check for status*/
status = newStatus;
}
if(close(fd[0]) == -1){
printf("Error closing reading end of pipe\n");
_exit(EXIT_FAILURE);
}
printf("Message has been received in wallClock()--Terminating now\n");
_exit(EXIT_SUCCESS);
}
void runFile(){
int status = RUN;
int newStatus;
pid_t pid;
if(close(fd[1]) == -1){ /*close all unused pipes*/
printf("Error closing writing end of pipe runFile\n");
_exit(EXIT_FAILURE);
}
if(close(fd[0]) == -1){
printf("Error closing reading end of pipe runFile\n");
_exit(EXIT_FAILURE);
}
if(close(fd2[1]) == -1){
printf("Error closing writing end of pipe2 in runFile\n");
_exit(EXIT_FAILURE);
}
while(status != STOP){ /* wait until signal occurs */
if((pid = fork()) == -1){ /*create fork within child process to run exec */
printf("Fork failed\n");
_exit(EXIT_FAILURE);
}
else if(pid == 0){
execl("/usr/bin/uptime", "uptime", NULL);
printf("exec failed!\n");
_exit(EXIT_FAILURE);
}
else{ /*parent handler*/
int ret;
pid_t justLeft;
justLeft = wait(&ret);
read(fd2[0], &newStatus, sizeof(newStatus));
status = newStatus;
}
sleep(5);
}
printf("Signal has been received, closing pipes and exiting uptime mananger\n");
if(close(fd2[0]) == -1){
printf("Error closing reading end of runFile pipe\n");
_exit(EXIT_FAILURE);
}
_exit(EXIT_SUCCESS);
}
void countDown(int start){
int stopNow = STOP; /*signals*/
int cont = RUN;
if(close(fd[0]) == -1){ /*close all unused pipes*/
printf("Error closing reading end of pipe in countDown\n");
_exit(EXIT_FAILURE);
}
if(close(fd2[0]) == -1){
printf("Error closing reading end of pipe2 in countDown\n");
_exit(EXIT_FAILURE);
}
while(start > 0){ /*while loop until start reaches 0*/
if(start >= 10){
printf("Count Down: 00:%2d\n", start);
}
else{
printf("Count Down: 00:0%d\n", start);
}
write(fd[1], &cont, sizeof(cont)); /*write in pipe to continue still*/
write(fd2[1], &cont, sizeof(cont));
start--;
sleep(1);
}
printf("Count Down: 00:00 -- sending message to terminate other processess\n");
write(fd[1], &stopNow, sizeof(stopNow)); /*Tell others to terminate*/
write(fd2[1], &stopNow, sizeof(stopNow));
if(close(fd[1]) == -1){
printf("Error closing writing end of pipe in countDown\n");
_exit(EXIT_FAILURE);
}
if(close(fd2[1]) == -1){
printf("Error closing writing end of pipe2 in countDown\n");
_exit(EXIT_FAILURE);
}
_exit(EXIT_SUCCESS);
}
int main(int argc, char *argv[]){
int time , i, status, newStatus, ret, n, newChild, numExited;
pid_t child[NUMBEROFCHILD];
pid_t pid;
if(argc <= 2){ /*check arguments*/
if(argv[1] != '\0'){
time = atoi(argv[1]);
}
else
time = DEFAULT;
}
else{
printf("Too many parameters -- exiting program\n");
return -1;
}
if(pipe(fd) == -1){ /*open pipes*/
printf("Error opening pipe\n");
exit(EXIT_FAILURE);
}
if(pipe(fd2) == -1){
printf("Error opening pipe\n");
exit(EXIT_FAILURE);
}
for(i = 0; i < NUMBEROFCHILD; i++){ /* create children */
if((child[i] = fork()) == -1){
printf("Error in creating child\n");
exit(EXIT_FAILURE);
}
if(child[i] == 0){
switch(i){
case 0: wallClock();
break;
case 1: runFile();
break;
case 2: countDown(time);
break;
}
}
}
if(close(fd[1]) == -1){
printf("Error closing parent reading pipe\n");
exit(EXIT_FAILURE);
}
if(close(fd[0]) == -1){
printf("Error closing parent writing pipe\n");
exit(EXIT_FAILURE);
}
if(close(fd2[1]) == -1){
printf("Error closing parent reading pipe2\n");
exit(EXIT_FAILURE);
}
if(close(fd2[0]) == -1){
printf("Error closing parent writing pipe2\n");
exit(EXIT_FAILURE);
}
n = NUMBEROFCHILD;
while(n > 0){ /*Wait for all children to finish*/
pid = wait(&status);
if(pid == -1){
printf("Error exiting with childPID %d\n", pid);
exit(EXIT_FAILURE);
}
--n;
printf("Child %d has exited successfully\n", pid);
}
printf("All processes has ended, exiting program --\n");
return 0;
}
Code:
> gcc -g assign3.c
> a.out 15
Count Down: 00:15
the time is 18:5:25
6:05pm up 279 day(s), 8:52, 27 users, load average: 3.48, 3.78, 4.80
Count Down: 00:14
the time is 18:5:26
Count Down: 00:13
the time is 18:5:27
Count Down: 00:12
the time is 18:5:28
Count Down: 00:11
the time is 18:5:29
Count Down: 00:10
the time is 18:5:30
6:05pm up 279 day(s), 8:52, 27 users, load average: 3.46, 3.77, 4.79
the time is 18:5:31
Count Down: 00:09
the time is 18:5:32
Count Down: 00:08
the time is 18:5:33
Count Down: 00:07
Count Down: 00:06
the time is 18:5:34
Count Down: 00:05
the time is 18:5:35
6:05pm up 279 day(s), 8:52, 27 users, load average: 3.45, 3.76, 4.79
Count Down: 00:04
the time is 18:5:36
the time is 18:5:37
Count Down: 00:03
Count Down: 00:02
the time is 18:5:38
the time is 18:5:39
Count Down: 00:01
the time is 18:5:40
Count Down: 00:00 -- sending message to terminate other processess
Child 9779 has exited successfully
6:05pm up 279 day(s), 8:52, 27 users, load average: 3.44, 3.75, 4.77
Message has been received in wallClock()--Terminating now
Child 9777 has exited successfully
6:05pm up 279 day(s), 8:52, 27 users, load average: 3.42, 3.74, 4.77
6:05pm up 279 day(s), 8:52, 27 users, load average: 3.40, 3.73, 4.76
6:05pm up 279 day(s), 8:52, 27 users, load average: 3.39, 3.72, 4.75
6:06pm up 279 day(s), 8:52, 27 users, load average: 3.38, 3.71, 4.74
6:06pm up 279 day(s), 8:53, 27 users, load average: 3.36, 3.71, 4.73
6:06pm up 279 day(s), 8:53, 26 users, load average: 3.37, 3.70, 4.73
6:06pm up 279 day(s), 8:53, 26 users, load average: 3.46, 3.71, 4.72
6:06pm up 279 day(s), 8:53, 26 users, load average: 3.87, 3.80, 4.75
6:06pm up 279 day(s), 8:53, 26 users, load average: 4.59, 3.95, 4.79
6:06pm up 279 day(s), 8:53, 27 users, load average: 5.29, 4.10, 4.84
6:06pm up 279 day(s), 8:53, 27 users, load average: 5.84, 4.23, 4.88
6:06pm up 279 day(s), 8:53, 27 users, load average: 6.36, 4.37, 4.92
Signal has been received, closing pipes and exiting uptime mananger
Child 9778 has exited successfully
All processes has ended, exiting program --