diff options
author | dzwdz | 2021-09-21 17:26:36 +0200 |
---|---|---|
committer | dzwdz | 2021-09-21 17:26:36 +0200 |
commit | d34bd9a45440be2ef65d24619af5505b8c05c229 (patch) | |
tree | e404c0cce84b52e2c18e579ca0cd807e329e8847 | |
parent | 4e915aabfc68eb43f71010f7856d486e0164ce56 (diff) |
make await() fail gracefully when callee has no alive children already
-rw-r--r-- | src/init/main.c | 9 | ||||
-rw-r--r-- | src/kernel/syscalls.c | 16 |
2 files changed, 15 insertions, 10 deletions
diff --git a/src/init/main.c b/src/init/main.c index 558fb77..8e78b87 100644 --- a/src/init/main.c +++ b/src/init/main.c @@ -80,16 +80,17 @@ void fs_test(void) { void test_await(void) { char buf[16]; int len; + // the child immediately dies if (!_syscall_fork()) _syscall_exit(argify("i'm dead")); + if (!_syscall_fork()) + _syscall_exit(argify("i'm also dead")); - len = _syscall_await(buf, 16); - if (len < 0) { - log("await: negative len\n"); - } else { + while ((len = _syscall_await(buf, 16)) >= 0) { log("await returned: "); _syscall_write(tty_fd, buf, len, 0); log("\n"); } + log("await: negative len\n"); } diff --git a/src/kernel/syscalls.c b/src/kernel/syscalls.c index 0ca7867..ac21cdb 100644 --- a/src/kernel/syscalls.c +++ b/src/kernel/syscalls.c @@ -39,22 +39,26 @@ _Noreturn void _syscall_exit(const char __user *msg, size_t len) { } int _syscall_await(char __user *buf, int len) { + bool has_children = false; process_current->state = PS_WAITS4CHILDDEATH; process_current->death_msg.buf = buf; process_current->death_msg.len = len; // find any already dead children for (struct process *iter = process_current->child; - iter; iter = iter->sibling) - { + iter; iter = iter->sibling) { if (iter->state == PS_DEAD) await_finish(iter, process_current); // doesn't return + if (iter->state != PS_DEADER) + has_children = true; } - // no dead children yet - // TODO check if the process even has children - - process_switch_any(); + if (has_children) + process_switch_any(); // wait until a child dies + else { + process_current->state = PS_RUNNING; + return -1; // error + } } int _syscall_fork(void) { |