From a6557ed0233e2193cef0ab5b4cea7f1d7f19ad5d Mon Sep 17 00:00:00 2001 From: Kimplul Date: Thu, 4 Jul 2024 23:40:37 +0300 Subject: use notification framework for orphanizing threads --- src/uapi/ipc.c | 15 +++++++++------ src/uapi/proc.c | 26 ++++++++++++++++++-------- 2 files changed, 27 insertions(+), 14 deletions(-) (limited to 'src/uapi') diff --git a/src/uapi/ipc.c b/src/uapi/ipc.c index bc49dbb..ddc7242 100644 --- a/src/uapi/ipc.c +++ b/src/uapi/ipc.c @@ -138,8 +138,8 @@ static bool __enough_rpc_stack(struct tcb *t) /** * Actually run notification handler, no ifs or buts. * - * @param t Previous thread. - * @param r Next thread. + * @param t Current thread. + * @param r Process where notification handler is. * * \p t and \p r may be the same thread. */ @@ -148,12 +148,15 @@ static __noreturn void __run_notify(struct tcb *t, struct tcb *r) use_tcb(r); enum sys_user code = SYS_USER_NOTIFY; - /* if we're not in RPC, we can safely notify of a signal while we're at - * it */ - enum notify_flag flags = is_rpc(t) ? 0 : NOTIFY_SIGNAL; + enum notify_flag flags = 0; + + /* if we're in the root process, we can safely handle signals and + * becoming orphaned */ + if (!is_rpc(t)) + set_bits(flags, t->notify_flags & (NOTIFY_SIGNAL | NOTIFY_ORPHANED)); /* handle critical notifications with special care */ - if (is_set(flags, NOTIFY_IRQ | NOTIFY_TIMER)) { + if (is_set(t->notify_flags, NOTIFY_IRQ | NOTIFY_TIMER)) { set_bits(flags, t->notify_flags & (NOTIFY_IRQ | NOTIFY_TIMER)); disable_irqs(); } diff --git a/src/uapi/proc.c b/src/uapi/proc.c index 231cc32..5b64dce 100644 --- a/src/uapi/proc.c +++ b/src/uapi/proc.c @@ -92,10 +92,17 @@ SYSCALL_DEFINE0(fork)(struct tcb *t) SYSCALL_DEFINE2(exec)(struct tcb *t, sys_arg_t bin, sys_arg_t interp) { /** @todo probably make sure thread is root thread of process? */ + if (!is_proc(t)) + return_args1(t, ERR_PERM); + + /* exec is only allowed if we own all our own resources */ + if (t->refcount) + return_args1(t, ERR_INVAL) + /* mark binary to be kept */ struct mem_region *b = find_used_region(&t->sp_r, bin); if (!b) - return_args1(t, ERR_INVAL); + return_args1(t, ERR_ADDR); set_bit(b->flags, MR_KEEP); @@ -237,28 +244,31 @@ SYSCALL_DEFINE1(exit)(struct tcb *t, sys_arg_t tid) /** * Syscall handler for orphanizing a thread. * - * @param t Thread that wants to make itself an orphant. + * @param t Current thread. + * @param tid Thread we want to orphanize. May be ourselves. * @return \ref OK on success, * \ref ERR_PERM if current process missing \ref CAP_PROC, * \ref ERR_INVAL if already an orphant. */ -SYSCALL_DEFINE0(detach)(struct tcb *t) +SYSCALL_DEFINE1(detach)(struct tcb *t, sys_arg_t tid) { struct tcb *c = get_cproc(t); if (!(has_cap(c->caps, CAP_PROC))) return_args1(t, ERR_PERM); - if (orphan(t)) + struct tcb *o = get_tcb(tid); + if (!o || orphan(o)) return_args1(t, ERR_INVAL); - struct tcb *r = get_tcb(t->rid); + struct tcb *r = get_tcb(o->rid); if (r) unreference_proc(r); - orphanize(t); + orphanize(o); - if (!is_rpc(t)) - unorphanize(t); + /* generally the thread shouldn't do anything with this information, but + * it fits really nicely into the notification framework so just do it */ + notify(o, NOTIFY_ORPHANED); return_args1(t, OK); } -- cgit v1.3