summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/init/main.c9
-rw-r--r--src/kernel/syscalls.c16
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) {