Skip to content

Commit 5c70b34

Browse files
committed
default code of -1 provides false positives to WIFSTOPPED
1 parent 40c092f commit 5c70b34

File tree

2 files changed

+50
-35
lines changed

2 files changed

+50
-35
lines changed

runtime/process-posix.c

+49-35
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
//============================================================
1010

1111
// 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.
1313
// - fin/fout/ferr: The stdin/stdout/stderr streams for communicating with the child.
1414
// NULL if child uses stdin/stdout/stderr directly.
1515
// - status: Pointer to location to write status code when child is terminated.
@@ -19,7 +19,7 @@ typedef struct ChildProcess {
1919
FILE* fin;
2020
FILE* fout;
2121
FILE* ferr;
22-
stz_int* status;
22+
ProcessStatus* pstatus;
2323
} ChildProcess;
2424

2525
// Represents a linked list of ChildProcess.
@@ -69,7 +69,7 @@ static void remove_child_process (pid_t pid) {
6969
prev = curr;
7070
curr = curr->next;
7171
}
72-
72+
7373
// Remove child process from list if one was found.
7474
if(curr != NULL){
7575
if(prev == NULL)
@@ -95,17 +95,18 @@ static void register_child_process (
9595

9696
// Initialize and save ProcessStatus struct.
9797
ProcessStatus* st = (ProcessStatus*)malloc(sizeof(ProcessStatus));
98+
st->code_set = 0;
9899
st->status_code = -1;
99100
*status = st;
100-
101+
101102
// Initialize ChildProcess struct.
102103
ChildProcess* child = (ChildProcess*)malloc(sizeof(ChildProcess));
103104
child->pid = pid;
104105
child->fin = fin;
105106
child->fout = fout;
106107
child->ferr = ferr;
107-
child->status = &(st->status_code);
108-
108+
child->pstatus = st; //;&(st->status_code);
109+
109110
// Store child in ChildProcessList
110111
add_child_process(child);
111112
}
@@ -121,13 +122,23 @@ static bool is_dead_status (stz_int status_code) {
121122
return WIFSIGNALED(status_code) || WIFEXITED(status_code);
122123
}
123124

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+
124133
// Update the status code for the registered child process
125134
// with the given process id.
126135
// Precondition: SIGCHLD is blocked
127136
static void set_child_status (pid_t pid, stz_int status_code) {
128137
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+
}
131142
}
132143

133144
// Update the current status of the given registered child process.
@@ -257,15 +268,19 @@ static void restore_signal_mask (sigset_t* old_mask) {
257268
//============================================================
258269

259270
//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+
}
269284
}
270285

271286
// Retrieve the state of the given process.
@@ -276,26 +291,25 @@ ProcessState make_process_state (stz_int status_code){
276291
stz_int retrieve_process_state (Process* process,
277292
ProcessState* s,
278293
stz_int wait_for_termination){
279-
294+
280295
//Block SIGCHLD while we're reading the process state.
281296
sigset_t old_signal_mask = block_sigchild();
282297

283298
//Read the current status code of the process.
284-
stz_int status = process->status->status_code;
299+
ProcessStatus* pstatus = process->status;
285300

286301
//If we need to wait for termination, then
287302
//call suspend_until_sigchild repeatedly until
288303
//process is dead.
289304
if(wait_for_termination){
290-
while(!is_dead_status(status)){
305+
while(!is_process_dead(pstatus)){
291306
suspend_until_sigchild();
292-
status = process->status->status_code;
293-
}
307+
}
294308
}
295309

296310
//Store the status code as a Stanza ProcessState.
297-
*s = make_process_state(status);
298-
311+
*s = make_process_state(pstatus);
312+
299313
//End Block SIGCHLD.
300314
restore_signal_mask(&old_signal_mask);
301315

@@ -321,11 +335,11 @@ stz_int retrieve_process_state (Process* process,
321335
//}
322336

323337
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,
325339
stz_byte* working_dir, stz_byte** env_vars, Process* process) {
326340
//block sigchld
327341
sigset_t old_signal_mask = block_sigchild();
328-
342+
329343
//Compute which pipes to create for the process.
330344
//has_pipes[PROCESS_IN] = 1, indicates that a process input pipe
331345
//needs to be created.
@@ -368,9 +382,9 @@ stz_int launch_process(stz_byte* file, stz_byte** argvs,
368382
goto return_error;
369383
if(error == PROCESS_OUT)
370384
if(posix_spawn_file_actions_adddup2(&actions, pipes[PROCESS_OUT][1], STDERR_FILENO))
371-
goto return_error;
385+
goto return_error;
372386
if(posix_spawn_file_actions_addclose(&actions, pipes[PROCESS_OUT][1]))
373-
goto return_error;
387+
goto return_error;
374388
}
375389
//Connect process error pipe if necessary.
376390
if(has_pipes[PROCESS_ERR]){
@@ -383,7 +397,7 @@ stz_int launch_process(stz_byte* file, stz_byte** argvs,
383397
if(posix_spawn_file_actions_adddup2(&actions, pipes[PROCESS_ERR][1], STDOUT_FILENO))
384398
goto return_error;
385399
if(posix_spawn_file_actions_addclose(&actions, pipes[PROCESS_ERR][1]))
386-
goto return_error;
400+
goto return_error;
387401
}
388402

389403
//Setup working directory
@@ -456,9 +470,9 @@ stz_int launch_process(stz_byte* file, stz_byte** argvs,
456470
#ifdef PLATFORM_LINUX
457471

458472
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,
460474
stz_byte* working_dir, stz_byte** env_vars, Process* process) {
461-
475+
462476
//Compute which pipes to create for the process.
463477
//has_pipes[PROCESS_IN] = 1, indicates that a process input pipe
464478
//needs to be created.
@@ -481,7 +495,7 @@ stz_int launch_process(stz_byte* file, stz_byte** argvs, stz_int input,
481495
// Fork child process
482496
stz_long pid = (stz_long)vfork();
483497
if(pid < 0) return -1;
484-
498+
485499
// Parent: if exec succeeded, open files, register with signal handler
486500
if(pid > 0) {
487501

@@ -526,14 +540,14 @@ stz_int launch_process(stz_byte* file, stz_byte** argvs, stz_int input,
526540
restore_signal_mask(&old_signal_mask);
527541
return -1;
528542
}
529-
543+
530544
//Perform cleanup and return 0 to indicate success.
531545
return_success: {
532546
restore_signal_mask(&old_signal_mask);
533547
return 0;
534548
}
535549
}
536-
550+
537551
// Child: setup pipes, exec
538552
else {
539553
//Connect process input pipe if necessary.
@@ -560,7 +574,7 @@ stz_int launch_process(stz_byte* file, stz_byte** argvs, stz_int input,
560574
if(dup2(pipes[PROCESS_ERR][1], STDERR_FILENO) < 0) exit(-1);
561575
if(close(pipes[PROCESS_ERR][1]) < 0) exit(-1);
562576
}
563-
577+
564578
//Setup working directory
565579
if(working_dir) {
566580
if(chdir(C_CSTR(working_dir)) < 0) exit(-1);

runtime/process.h

+1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
//- status_code: Holds the POSIX status code of the process as communicated by
88
// the SIGCHILD signal.
99
typedef struct ProcessStatus {
10+
int code_set;
1011
stz_int status_code;
1112
} ProcessStatus;
1213

0 commit comments

Comments
 (0)