-
Notifications
You must be signed in to change notification settings - Fork 0
/
hw06-2.c
154 lines (122 loc) · 2.55 KB
/
hw06-2.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <string.h>
#include <sys/wait.h>
#include <stdlib.h>
// SIGALRM handler
void parent_alrm(int sig);
void child_alrm(int sig);
// SIGINT handler
void parent_int(int sig);
void child_int(int sig);
// SIGCHLD handler
void read_childproc(int sig);
// error handler
void error_handling(char* message);
// global variable, processes don't share this
int time = 0;
// child process uses this
int cnt = 0;
int main()
{
int pid = fork();
if(pid == -1)
error_handling("fork() error");
// child process
if(pid == 0)
{
// assign SIGALRM handler
struct sigaction act_child;
act_child.sa_handler = child_alrm;
sigemptyset(&act_child.sa_mask);
act_child.sa_flags = 0;
sigaction(SIGALRM, &act_child, NULL);
// assign SIGINT handler
struct sigaction dontint;
dontint.sa_handler = child_int;
sigemptyset(&dontint.sa_mask);
dontint.sa_flags = 0;
sigaction(SIGINT, &dontint, NULL);
for(int i = 0; i < 5; i++)
{
alarm(5); // every 5 sec, SIGALRM
sleep(10); // wakes up by SIGALRM
}
return 5;
}
// parent process
else
{
struct sigaction act1;
struct sigaction act2;
struct sigaction act3;
// assign signal handlers
act1.sa_handler = parent_alrm;
sigemptyset(&act1.sa_mask);
act1.sa_flags = 0;
act2.sa_handler = parent_int;
sigemptyset(&act2.sa_mask);
act2.sa_flags = 0;
act3.sa_handler = read_childproc;
sigemptyset(&act3.sa_mask);
act3.sa_flags = 0;
sigaction(SIGALRM, &act1, NULL);
sigaction(SIGINT, &act2, NULL);
sigaction(SIGCHLD, &act3, NULL);
alarm(2);
while(1)
{
sleep(1); // Infinite Looping
}
}
return 0;
}
// SIGALRM
void child_alrm(int sig)
{
time += 5;
cnt += 1;
printf("[Child] time out: 5, elapsed time: %d seconds(%d)\n", time, cnt);
}
void parent_alrm(int sig)
{
time += 2;
printf("<Parent> time out: 2, elapsed time: %d seconds\n", time);
alarm(2); // alarm makes alarm
}
// SIGINT
void parent_int(int sig)
{
printf("Do you want to exit (y or Y to exit)?\n");
char buf[100]= {0};
fgets(buf, 100, stdin);
if(strcmp(buf, "y\n") == 0 || strcmp(buf, "Y\n") == 0)
{
exit(0);
}
else
sleep(2); // don't wake up by SIGINT
}
void child_int(int sig)
{
sleep(10); // don't die by SIGINT
return;
}
// SIGCHLD
void read_childproc(int sig)
{
int status;
pid_t id = waitpid(-1, &status, WNOHANG);
if(WIFEXITED(status))
{
printf("Child id = %d, sent: %d\n", id, WEXITSTATUS(status));
}
}
// error handling
void error_handling(char* message)
{
fputs(message, stderr);
fputc('\n', stderr);
exit(1);
}