4
4
#include <spawn.h>
5
5
#include "process.h"
6
6
7
+ //============================================================
8
+ //=================== Lock Assumption ========================
9
+ //============================================================
10
+
11
+ volatile int locked = 0 ;
12
+
13
+ void assert_lock (char * ctxt ) {
14
+ if (!locked ){
15
+ printf ("ERROR: Lock is assumed to be obtained but isn't. (%s)\n" , ctxt );
16
+ exit (-1 );
17
+ }
18
+ }
19
+
20
+ void obtain_lock (char * ctxt ) {
21
+ if (locked ){
22
+ printf ("ERROR: Cannot obtain lock. Lock is already assumed. (%s)\n" , ctxt );
23
+ exit (-1 );
24
+ }
25
+ locked = 1 ;
26
+ }
27
+
28
+ void release_lock (char * ctxt ) {
29
+ if (!locked ){
30
+ printf ("ERROR: Cannot release lock. Lock is not assumed. (%s)\n" , ctxt );
31
+ exit (-1 );
32
+ }
33
+ locked = 0 ;
34
+ }
35
+
7
36
//============================================================
8
37
//================= ChildProcess Registration ================
9
38
//============================================================
@@ -38,6 +67,7 @@ volatile ChildProcessList * volatile child_processes = NULL;
38
67
// Add a new ChildProcess to the global 'child_processes' list.
39
68
// Precondition: SIGCHLD is blocked
40
69
void add_child_process (ChildProcess * child ) {
70
+ assert_lock ("add_child_process" );
41
71
ChildProcessList * new_node = (ChildProcessList * )malloc (sizeof (ChildProcessList ));
42
72
new_node -> proc = child ;
43
73
new_node -> next = child_processes ;
@@ -47,6 +77,7 @@ void add_child_process (ChildProcess* child) {
47
77
// Return the ChildProcess with the given process id.
48
78
// Returns NULL if there is none.
49
79
static ChildProcess * get_child_process (pid_t pid ){
80
+ assert_lock ("get_child_process" );
50
81
volatile ChildProcessList * volatile curr = child_processes ;
51
82
while (curr != NULL && curr -> proc -> pid != pid )
52
83
curr = curr -> next ;
@@ -58,6 +89,7 @@ static ChildProcess* get_child_process (pid_t pid){
58
89
// 'child_processes' list if it exists in the list.
59
90
// Precondition: SIGCHLD is blocked
60
91
static void remove_child_process (pid_t pid ) {
92
+ assert_lock ("remove_child_process" );
61
93
62
94
// Find the ChildProcess with matching pid.
63
95
// After this loop, either:
@@ -92,6 +124,7 @@ static void register_child_process (
92
124
FILE * fout ,
93
125
FILE * ferr ,
94
126
ProcessStatus * * status ) {
127
+ assert_lock ("register_child_process" );
95
128
96
129
// Initialize and save ProcessStatus struct.
97
130
ProcessStatus * st = (ProcessStatus * )malloc (sizeof (ProcessStatus ));
@@ -125,6 +158,7 @@ static bool is_dead_status (stz_int status_code) {
125
158
// with the given process id.
126
159
// Precondition: SIGCHLD is blocked
127
160
static void set_child_status (pid_t pid , stz_int status_code ) {
161
+ assert_lock ("set_child_status" );
128
162
ChildProcess * proc = get_child_process (pid );
129
163
if (proc != NULL )
130
164
* (proc -> status ) = status_code ;
@@ -135,6 +169,8 @@ static void set_child_status (pid_t pid, stz_int status_code) {
135
169
// metadata struct.
136
170
// Precondition: SIGCHLD is blocked
137
171
static void update_child_status (pid_t pid ) {
172
+ assert_lock ("update_child_status" );
173
+
138
174
//Retrieve the status of the given process.
139
175
int status ;
140
176
int ret_pid = waitpid (pid , & status , WNOHANG | WUNTRACED | WCONTINUED );
@@ -151,6 +187,8 @@ static void update_child_status (pid_t pid) {
151
187
// Update the current status of all registered child processes.
152
188
// Precondition: SIGCHLD is blocked
153
189
static void update_all_child_statuses () {
190
+ assert_lock ("update_all_child_statuses" );
191
+
154
192
volatile ChildProcessList * volatile curr = child_processes ;
155
193
while (curr != NULL ) {
156
194
//NOTE: curr->next is retrieved preemptively because
@@ -176,6 +214,8 @@ struct sigaction old_sigchild_action;
176
214
// be executed if it is already in the middle of executing. SIGCHILD
177
215
// must be blocked.
178
216
void autoreaping_sigchld_handler (int sig ){
217
+ obtain_lock ("autoreaping_sigchld_handler" );
218
+
179
219
//Update the statuses of all registered child processes.
180
220
update_all_child_statuses ();
181
221
@@ -189,6 +229,8 @@ void autoreaping_sigchld_handler(int sig){
189
229
old_sigchild_action .sa_handler != SIG_IGN ){
190
230
old_sigchild_action .sa_handler (sig );
191
231
}
232
+
233
+ release_lock ("autoreaping_sigchld_handler" );
192
234
}
193
235
194
236
// This installs the autoreaping signal handler.
@@ -215,6 +257,8 @@ void install_autoreaping_sigchld_handler () {
215
257
//Blocks the SIGCHILD signal by updating the signal mask.
216
258
//Returns the previous signal mask.
217
259
static sigset_t block_sigchild () {
260
+ obtain_lock ("block_sigchild" );
261
+
218
262
//Create signal mask containing only SIGCHLD.
219
263
sigset_t sigchld_mask ;
220
264
sigemptyset (& sigchld_mask );
@@ -250,6 +294,7 @@ static void suspend_until_sigchild () {
250
294
static void restore_signal_mask (sigset_t * old_mask ) {
251
295
if (sigprocmask (SIG_SETMASK , old_mask , NULL ))
252
296
exit_with_error ();
297
+ release_lock ("restore_signal_mask" );
253
298
}
254
299
255
300
//============================================================
0 commit comments