Commit cfbf4096 authored by Taddeüs Kroes's avatar Taddeüs Kroes

- Implemented signals in OS ass3.

parent ea3add61
...@@ -6,6 +6,8 @@ ...@@ -6,6 +6,8 @@
#include <errno.h> #include <errno.h>
#include <signal.h> #include <signal.h>
static pid_t parent_pid;
/* /*
* Read from pipe (child processes only). * Read from pipe (child processes only).
*/ */
...@@ -22,49 +24,47 @@ static void gup(FILE * log1, FILE * log2, int pipe_id[2], int myNumber) ...@@ -22,49 +24,47 @@ static void gup(FILE * log1, FILE * log2, int pipe_id[2], int myNumber)
fprintf(log1, "This is child number %d\n", myNumber); fprintf(log1, "This is child number %d\n", myNumber);
fprintf(log2, "This is child number %d\n", myNumber); fprintf(log2, "This is child number %d\n", myNumber);
/* just for sure - open one more log file .... */ /* Open a line buffered log. */
log3 = fopen("child.log3", "wt+"); log3 = fopen("child.log3", "wt+");
setvbuf(log3, NULL, _IOLBF, BUFSIZ); setvbuf(log3, NULL, _IOLBF, BUFSIZ);
/* log3 is line buffered - a line of output is written
immediately on encountering an end-of-line */
fprintf(log3, "This is child number %d\n", myNumber); fprintf(log3, "This is child number %d\n", myNumber);
do do
{ {
/* Read next character from pipe */ /* Read next character from pipe */
if( read(pipe_id[0], &c, 1) <= 0 ) if( read(pipe_id[0], &c, 1) <= 0 )
{ {
/* Error while reading from the pipe, exit */ /* Error while reading from the pipe, exit */
fprintf(log1, "Child %d read from pipe with error " fprintf(log1, "Child %d read from pipe with error "
"and exited \n", myNumber); "and exited \n", myNumber);
fprintf(log2, "Child %d read from pipe with error " fprintf(log2, "Child %d read from pipe with error "
"and exited \n", myNumber); "and exited \n", myNumber);
fprintf(log3, "Child %d read from pipe with error " fprintf(log3, "Child %d read from pipe with error "
"and exited \n", myNumber); "and exited \n", myNumber);
fclose(log1); fclose(log1);
fclose(log2); fclose(log2);
fclose(log3); fclose(log3);
exit(1); exit(1);
} }
/* Character read successfully, process it */ /* Character read successfully, process it */
fprintf(log1, "Child %d read character %x: '%c'\n", myNumber, c, c); fprintf(log1, "Child %d read character %x: '%c'\n", myNumber, c, c);
fprintf(log2, "Child %d read character %x: '%c'\n", myNumber, c, c); fprintf(log2, "Child %d read character %x: '%c'\n", myNumber, c, c);
fprintf(log3, "Child %d read character %x: '%c'\n", myNumber, c, c); fprintf(log3, "Child %d read character %x: '%c'\n", myNumber, c, c);
if( c == 'P' ) if( c == 'P' )
{ {
/* Decrease antidote level or exit the process */ /* Decrease antidote level or exit the process */
if( !antidote ) if( !antidote )
{ {
fprintf(log1, "Child %d has no antidote for poison " fprintf(log1, "Child %d has no antidote for poison "
"and will exit \n", myNumber); "and will exit \n", myNumber);
fprintf(log2, "Child %d has no antidote for poison " fprintf(log2, "Child %d has no antidote for poison "
"and will exit \n", myNumber); "and will exit \n", myNumber);
fprintf(log3, "Child %d has no antidote for poison " fprintf(log3, "Child %d has no antidote for poison "
"and will exit \n", myNumber); "and will exit \n", myNumber);
break; break;
} }
else else
{ {
...@@ -72,11 +72,11 @@ static void gup(FILE * log1, FILE * log2, int pipe_id[2], int myNumber) ...@@ -72,11 +72,11 @@ static void gup(FILE * log1, FILE * log2, int pipe_id[2], int myNumber)
fprintf(log1, "antidote used (%d left) \n", antidote); fprintf(log1, "antidote used (%d left) \n", antidote);
fprintf(log2, "antidote used (%d left) \n", antidote); fprintf(log2, "antidote used (%d left) \n", antidote);
fprintf(log3, "antidote used (%d left) \n", antidote); fprintf(log3, "antidote used (%d left) \n", antidote);
} }
} }
else if( c == 'A' ) else if( c == 'A' )
{ {
/* Increase antidote level */ /* Increase antidote level */
antidote++; antidote++;
fprintf(log1, "Child %d finds antidote (now has %d) \n", fprintf(log1, "Child %d finds antidote (now has %d) \n",
myNumber, antidote); myNumber, antidote);
...@@ -87,7 +87,7 @@ static void gup(FILE * log1, FILE * log2, int pipe_id[2], int myNumber) ...@@ -87,7 +87,7 @@ static void gup(FILE * log1, FILE * log2, int pipe_id[2], int myNumber)
} }
} while( c != '\0' ); } while( c != '\0' );
/* Close logs and exit normally */ /* Close logs and exit normally */
fprintf(log1, "Child %d normal exit \n", myNumber); fprintf(log1, "Child %d normal exit \n", myNumber);
fprintf(log2, "Child %d normal exit \n", myNumber); fprintf(log2, "Child %d normal exit \n", myNumber);
fprintf(log3, "Child %d normal exit \n", myNumber); fprintf(log3, "Child %d normal exit \n", myNumber);
...@@ -103,18 +103,34 @@ static void gup(FILE * log1, FILE * log2, int pipe_id[2], int myNumber) ...@@ -103,18 +103,34 @@ static void gup(FILE * log1, FILE * log2, int pipe_id[2], int myNumber)
void void
signal_handler(int signum) signal_handler(int signum)
{ {
switch( signum ) char *sig = "TERM";
{ pid_t pid;
case SIGINT:
switch( signum )
break; {
case SIGTERM: case SIGINT:
sig = "INT";
break; case SIGTERM:
case SIGCHLD: if( (pid = getpid()) == parent_pid )
{
break; printf("Parent process received SIG%s and will exit \n", sig);
} }
else
{
printf("Process with id %d received SIG%s and will exit \n",
pid, sig);
}
exit(1);
case SIGCHLD:
puts("Parent process received SIGCHLD");
pid = wait(NULL);
printf("Child with id %d exited \n", pid);
break;
default:
puts("This handler is unapplicable for this type of signal");
}
errno = 0;
} }
/* /*
...@@ -126,38 +142,54 @@ main(int argc, char * argv[]) ...@@ -126,38 +142,54 @@ main(int argc, char * argv[])
FILE * log1; FILE * log1;
FILE * log2; FILE * log2;
char c; char c;
int kiddoCount = 0, pipe_id[2];//, i = 1; int kiddoCount = 0, pipe_id[2];
struct sigaction action; struct sigaction action = {.sa_handler = signal_handler};
/* Save parent process id for signal handler */
parent_pid = getpid();
/* Open one buffered and one unbuffered log */
printf("argc: %d\n", argc); printf("argc: %d\n", argc);
log1 = fopen("child.log1", "wt+"); log1 = fopen("child.log1", "wt+");
log2 = fopen("child.log2", "wt+"); log2 = fopen("child.log2", "wt+");
setvbuf(log2, NULL, _IONBF, BUFSIZ); setvbuf(log2, NULL, _IONBF, BUFSIZ);
/* So log1 is buffered; log2 is not buffered, which means that output
* to log2 is written immediately. */
/* Create pipe, exit with error on failure */ /* Create pipe, exit with error on failure */
if( pipe(pipe_id) ) if( pipe(pipe_id) )
{ {
fprintf(stderr, "Error %d occured while creating the pipe \n", fprintf(stderr, "Error %d occured while creating the pipe \n",
errno); errno);
exit(1); exit(1);
} }
/* Bind signal handlers */ /* Bind signal handlers */
action.sa_handler = signal_handler; if( sigaction(SIGINT, &action, NULL)
+ sigaction(SIGTERM, &action, NULL)
if( sigaction(SIGINT, &action, NULL) < 0 + sigaction(SIGCHLD, &action, NULL) < 0 )
|| sigaction(SIGTERM, &action, NULL) < 0 {
|| sigaction(SIGCHLD, &action, NULL) < 0 ) perror("An error occured while binding the signal handlers \n");
{ exit(1);
perror("An error occured while binding the signal handlers \n"); }
exit(1);
} /* Keep reading input */
/* Keep reading input */
while( (c = getchar()) ) while( (c = getchar()) )
{ {
if( c == EOF )
{
if( errno == EINTR )
{
/* Wait for signal handler to end */
continue;
}
else
{
puts("Error while reading input from stdin");
fclose(log1);
fclose(log2);
exit(1);
}
}
/* Ignore newlines and spaces */ /* Ignore newlines and spaces */
if( c == '\n' || c == 32 ) if( c == '\n' || c == 32 )
{ {
...@@ -170,25 +202,25 @@ main(int argc, char * argv[]) ...@@ -170,25 +202,25 @@ main(int argc, char * argv[])
if( c == 'q' ) if( c == 'q' )
{ {
/* Exit program */ /* Exit program */
break; break;
} }
else if( c != 'f' ) else if( c != 'f' )
{ {
/* Write character to pipe for child processes */ /* Write character to pipe for child processes */
if( write(pipe_id[1], &c, 1) != 1 ) if( write(pipe_id[1], &c, 1) <= 0 )
{ {
perror("Cannot write to pipe \n"); perror("Cannot write to pipe \n");
exit(1); exit(1);
} }
/* Wait for child process to 'eat the poison' */ /* Wait for child process to 'eat the poison' */
if( c == 'P' ) //if( c == 'P' )
wait(NULL); // wait(NULL);
} }
else else
{ {
pid_t child_id; pid_t child_id;
kiddoCount++; kiddoCount++;
...@@ -198,24 +230,26 @@ main(int argc, char * argv[]) ...@@ -198,24 +230,26 @@ main(int argc, char * argv[])
switch( (child_id = fork()) ) switch( (child_id = fork()) )
{ {
case -1: case -1:
/* An error occured while forking */ /* An error occured while forking */
perror("Child could not be created \n"); perror("Child could not be created \n");
exit(1); exit(1);
case 0: case 0:
/* Child process after fork: read from pipe */ /* Child process after fork: Start reading from pipe */
gup(log1, log2, pipe_id, kiddoCount); gup(log1, log2, pipe_id, kiddoCount);
break; break;
default: default:
/* Parent proces after fork: Print child's process id */ /* Parent proces after fork: Print child's process id */
fprintf(log1, "Started child process %d with id %d \n", fprintf(log1, "Started child process %d with id %d \n",
kiddoCount, child_id); kiddoCount, child_id);
fprintf(log2, "Started child process %d with id %d \n", fprintf(log2, "Started child process %d with id %d \n",
kiddoCount, child_id); kiddoCount, child_id);
printf("Started child process %d with id %d \n",
kiddoCount, child_id);
} }
} }
} }
/* Close logs and exit normally */ /* Close logs and exit normally */
fprintf(log1, "Program exited normally \n"); fprintf(log1, "Program exited normally \n");
fprintf(log2, "Program exited normally \n"); fprintf(log2, "Program exited normally \n");
fclose(log1); fclose(log1);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment