The reason for all this is that some devices (#mnt) issue syscalls when
closing the FD, and those syscalls could block.  If we were DYING, those
syscalls would immediately abort.  #mnt didn't handle this well, and
went into an infinite loop.

The root of the problem is that we want the process to be dying, but we
don't want its syscalls to abort immediately.  We *do* want them to
abort at some point (I think).

We previously split the DYING state into DYING and DYING_ABORT.  All
code that cared about DYING also cared about DYING and DYING_ABORT.  Now
the actual abort code only checks DYING_ABORT, and not DYING.

One subtle change is that we close the FDT *after* aborting syscalls.
Previously we aborted syscalls first.  Devices should have no problem
with closes with outstanding syscalls - for instance, a close while
someone is blocked on an FD.  The user shouldn't do that, but they
could, so devices should be ready.

Signed-off-by: Barret Rhoden <[email protected]>
---
 kern/src/kthread.c |  8 +++++---
 kern/src/process.c | 10 ++++++----
 2 files changed, 11 insertions(+), 7 deletions(-)

diff --git a/kern/src/kthread.c b/kern/src/kthread.c
index 88ac162a1fcf..468890b720e8 100644
--- a/kern/src/kthread.c
+++ b/kern/src/kthread.c
@@ -843,9 +843,11 @@ bool abort_sysc(struct proc *p, struct syscall *sysc)
 
 /* This will abort any abortables at the time the call was started for which
  * should_abort(cle, arg) returns true.  New abortables could be registered
- * concurrently.  The original for this is proc_destroy(), so DYING will be 
set,
+ * concurrently.
+ *
+ * One caller for this is proc_destroy(), in which case DYING_ABORT will be 
set,
  * and new abortables will quickly abort and dereg when they see their proc is
- * DYING. */
+ * DYING_ABORT. */
 static int __abort_all_sysc(struct proc *p,
                             bool (*should_abort)(struct cv_lookup_elm*, void*),
                             void *arg)
@@ -964,7 +966,7 @@ bool should_abort(struct cv_lookup_elm *cle)
 
        if (is_ktask(cle->kthread))
                return FALSE;
-       if (cle->proc && (cle->proc->state == PROC_DYING))
+       if (cle->proc && (cle->proc->state == PROC_DYING_ABORT))
                return TRUE;
        if (cle->sysc) {
                assert(cle->proc && (cle->proc == current));
diff --git a/kern/src/process.c b/kern/src/process.c
index ce190cec43d8..c020f6e21e2c 100644
--- a/kern/src/process.c
+++ b/kern/src/process.c
@@ -876,10 +876,6 @@ void proc_destroy(struct proc *p)
        spin_unlock(&p->proc_lock);
        /* Wake any of our kthreads waiting on children, so they can abort */
        cv_broadcast(&p->child_wait);
-       /* Abort any abortable syscalls.  This won't catch every sleeper, but 
future
-        * abortable sleepers are already prevented via the DYING state.  
(signalled
-        * DYING, no new sleepers will block, and now we wake all old 
sleepers). */
-       abort_all_sysc(p);
        /* we need to close files here, and not in free, since we could have a
         * refcnt indirectly related to one of our files.  specifically, if we 
have
         * a parent sleeping on our pipe, that parent won't wake up to decref 
until
@@ -890,6 +886,12 @@ void proc_destroy(struct proc *p)
         * Also note that any mmap'd files will still be mmapped.  You can 
close the
         * file after mmapping, with no effect. */
        close_fdt(&p->open_files, FALSE);
+       /* Abort any abortable syscalls.  This won't catch every sleeper, but 
future
+        * abortable sleepers are already prevented via the DYING_ABORT state.
+        * (signalled DYING_ABORT, no new sleepers will block, and now we wake 
all
+        * old sleepers). */
+       __proc_set_state(p, PROC_DYING_ABORT);
+       abort_all_sysc(p);
        /* Tell the ksched about our death, and which cores we freed up */
        __sched_proc_destroy(p, pc_arr, nr_cores_revoked);
        /* Tell our parent about our state change (to DYING) */
-- 
2.8.0.rc3.226.g39d4020

-- 
You received this message because you are subscribed to the Google Groups 
"Akaros" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to