9
9
//============================================================
10
10
11
11
// Holds all metadata for a spawned child process.
12
- // - pid: The process id of the child process itself.
12
+ // - pid: The process id of the child process itself.
13
13
// - fin/fout/ferr: The stdin/stdout/stderr streams for communicating with the child.
14
14
// NULL if child uses stdin/stdout/stderr directly.
15
15
// - status: Pointer to location to write status code when child is terminated.
@@ -19,7 +19,7 @@ typedef struct ChildProcess {
19
19
FILE * fin ;
20
20
FILE * fout ;
21
21
FILE * ferr ;
22
- stz_int * status ;
22
+ ProcessStatus * pstatus ;
23
23
} ChildProcess ;
24
24
25
25
// Represents a linked list of ChildProcess.
@@ -69,7 +69,7 @@ static void remove_child_process (pid_t pid) {
69
69
prev = curr ;
70
70
curr = curr -> next ;
71
71
}
72
-
72
+
73
73
// Remove child process from list if one was found.
74
74
if (curr != NULL ){
75
75
if (prev == NULL )
@@ -95,17 +95,18 @@ static void register_child_process (
95
95
96
96
// Initialize and save ProcessStatus struct.
97
97
ProcessStatus * st = (ProcessStatus * )malloc (sizeof (ProcessStatus ));
98
+ st -> code_set = 0 ;
98
99
st -> status_code = -1 ;
99
100
* status = st ;
100
-
101
+
101
102
// Initialize ChildProcess struct.
102
103
ChildProcess * child = (ChildProcess * )malloc (sizeof (ChildProcess ));
103
104
child -> pid = pid ;
104
105
child -> fin = fin ;
105
106
child -> fout = fout ;
106
107
child -> ferr = ferr ;
107
- child -> status = & (st -> status_code );
108
-
108
+ child -> pstatus = st ; //; &(st->status_code);
109
+
109
110
// Store child in ChildProcessList
110
111
add_child_process (child );
111
112
}
@@ -121,13 +122,23 @@ static bool is_dead_status (stz_int status_code) {
121
122
return WIFSIGNALED (status_code ) || WIFEXITED (status_code );
122
123
}
123
124
125
+ // If status value is unknown, process is still running
126
+ // Otherwise, inspect value
127
+ static bool is_process_dead (ProcessStatus * pstatus ) {
128
+ if (pstatus -> code_set )
129
+ return is_dead_status (pstatus -> status_code );
130
+ else return false;
131
+ }
132
+
124
133
// Update the status code for the registered child process
125
134
// with the given process id.
126
135
// Precondition: SIGCHLD is blocked
127
136
static void set_child_status (pid_t pid , stz_int status_code ) {
128
137
ChildProcess * proc = get_child_process (pid );
129
- if (proc != NULL )
130
- * (proc -> status ) = status_code ;
138
+ if (proc != NULL ) {
139
+ proc -> pstatus -> code_set = 1 ;
140
+ proc -> pstatus -> status_code = status_code ;
141
+ }
131
142
}
132
143
133
144
// Update the current status of the given registered child process.
@@ -257,15 +268,19 @@ static void restore_signal_mask (sigset_t* old_mask) {
257
268
//============================================================
258
269
259
270
//Create a Stanza ProcessState struct from a POSIX status code.
260
- ProcessState make_process_state (stz_int status_code ){
261
- if (WIFEXITED (status_code ))
262
- return (ProcessState ){PROCESS_DONE , WEXITSTATUS (status_code )};
263
- else if (WIFSIGNALED (status_code ))
264
- return (ProcessState ){PROCESS_TERMINATED , WTERMSIG (status_code )};
265
- else if (WIFSTOPPED (status_code ))
266
- return (ProcessState ){PROCESS_STOPPED , WSTOPSIG (status_code )};
267
- else
268
- return (ProcessState ){PROCESS_RUNNING , 0 };
271
+ ProcessState make_process_state (ProcessStatus * pstatus ){
272
+ if (pstatus -> code_set ) {
273
+ if (WIFEXITED (pstatus -> status_code ))
274
+ return (ProcessState ){PROCESS_DONE , WEXITSTATUS (pstatus -> status_code )};
275
+ else if (WIFSIGNALED (pstatus -> status_code ))
276
+ return (ProcessState ){PROCESS_TERMINATED , WTERMSIG (pstatus -> status_code )};
277
+ else if (WIFSTOPPED (pstatus -> status_code ))
278
+ return (ProcessState ){PROCESS_STOPPED , WSTOPSIG (pstatus -> status_code )};
279
+ else
280
+ return (ProcessState ){PROCESS_RUNNING , 0 };
281
+ } else {
282
+ return (ProcessState ){PROCESS_RUNNING , 0 };
283
+ }
269
284
}
270
285
271
286
// Retrieve the state of the given process.
@@ -276,26 +291,25 @@ ProcessState make_process_state (stz_int status_code){
276
291
stz_int retrieve_process_state (Process * process ,
277
292
ProcessState * s ,
278
293
stz_int wait_for_termination ){
279
-
294
+
280
295
//Block SIGCHLD while we're reading the process state.
281
296
sigset_t old_signal_mask = block_sigchild ();
282
297
283
298
//Read the current status code of the process.
284
- stz_int status = process -> status -> status_code ;
299
+ ProcessStatus * pstatus = process -> status ;
285
300
286
301
//If we need to wait for termination, then
287
302
//call suspend_until_sigchild repeatedly until
288
303
//process is dead.
289
304
if (wait_for_termination ){
290
- while (!is_dead_status ( status )){
305
+ while (!is_process_dead ( pstatus )){
291
306
suspend_until_sigchild ();
292
- status = process -> status -> status_code ;
293
- }
307
+ }
294
308
}
295
309
296
310
//Store the status code as a Stanza ProcessState.
297
- * s = make_process_state (status );
298
-
311
+ * s = make_process_state (pstatus );
312
+
299
313
//End Block SIGCHLD.
300
314
restore_signal_mask (& old_signal_mask );
301
315
@@ -321,11 +335,11 @@ stz_int retrieve_process_state (Process* process,
321
335
//}
322
336
323
337
stz_int launch_process (stz_byte * file , stz_byte * * argvs ,
324
- stz_int input , stz_int output , stz_int error ,
338
+ stz_int input , stz_int output , stz_int error ,
325
339
stz_byte * working_dir , stz_byte * * env_vars , Process * process ) {
326
340
//block sigchld
327
341
sigset_t old_signal_mask = block_sigchild ();
328
-
342
+
329
343
//Compute which pipes to create for the process.
330
344
//has_pipes[PROCESS_IN] = 1, indicates that a process input pipe
331
345
//needs to be created.
@@ -368,9 +382,9 @@ stz_int launch_process(stz_byte* file, stz_byte** argvs,
368
382
goto return_error ;
369
383
if (error == PROCESS_OUT )
370
384
if (posix_spawn_file_actions_adddup2 (& actions , pipes [PROCESS_OUT ][1 ], STDERR_FILENO ))
371
- goto return_error ;
385
+ goto return_error ;
372
386
if (posix_spawn_file_actions_addclose (& actions , pipes [PROCESS_OUT ][1 ]))
373
- goto return_error ;
387
+ goto return_error ;
374
388
}
375
389
//Connect process error pipe if necessary.
376
390
if (has_pipes [PROCESS_ERR ]){
@@ -383,7 +397,7 @@ stz_int launch_process(stz_byte* file, stz_byte** argvs,
383
397
if (posix_spawn_file_actions_adddup2 (& actions , pipes [PROCESS_ERR ][1 ], STDOUT_FILENO ))
384
398
goto return_error ;
385
399
if (posix_spawn_file_actions_addclose (& actions , pipes [PROCESS_ERR ][1 ]))
386
- goto return_error ;
400
+ goto return_error ;
387
401
}
388
402
389
403
//Setup working directory
@@ -456,9 +470,9 @@ stz_int launch_process(stz_byte* file, stz_byte** argvs,
456
470
#ifdef PLATFORM_LINUX
457
471
458
472
stz_int launch_process (stz_byte * file , stz_byte * * argvs , stz_int input ,
459
- stz_int output , stz_int error ,
473
+ stz_int output , stz_int error ,
460
474
stz_byte * working_dir , stz_byte * * env_vars , Process * process ) {
461
-
475
+
462
476
//Compute which pipes to create for the process.
463
477
//has_pipes[PROCESS_IN] = 1, indicates that a process input pipe
464
478
//needs to be created.
@@ -481,7 +495,7 @@ stz_int launch_process(stz_byte* file, stz_byte** argvs, stz_int input,
481
495
// Fork child process
482
496
stz_long pid = (stz_long )vfork ();
483
497
if (pid < 0 ) return -1 ;
484
-
498
+
485
499
// Parent: if exec succeeded, open files, register with signal handler
486
500
if (pid > 0 ) {
487
501
@@ -526,14 +540,14 @@ stz_int launch_process(stz_byte* file, stz_byte** argvs, stz_int input,
526
540
restore_signal_mask (& old_signal_mask );
527
541
return -1 ;
528
542
}
529
-
543
+
530
544
//Perform cleanup and return 0 to indicate success.
531
545
return_success : {
532
546
restore_signal_mask (& old_signal_mask );
533
547
return 0 ;
534
548
}
535
549
}
536
-
550
+
537
551
// Child: setup pipes, exec
538
552
else {
539
553
//Connect process input pipe if necessary.
@@ -560,7 +574,7 @@ stz_int launch_process(stz_byte* file, stz_byte** argvs, stz_int input,
560
574
if (dup2 (pipes [PROCESS_ERR ][1 ], STDERR_FILENO ) < 0 ) exit (-1 );
561
575
if (close (pipes [PROCESS_ERR ][1 ]) < 0 ) exit (-1 );
562
576
}
563
-
577
+
564
578
//Setup working directory
565
579
if (working_dir ) {
566
580
if (chdir (C_CSTR (working_dir )) < 0 ) exit (-1 );
0 commit comments