On 2016-07-20 at 17:14 Barret Rhoden <[email protected]> wrote: > Hi - > > Kyle et al. stumbled on a bug with devmnt and exit-without-close. > > If you open a file across a 9p mount, then exit without calling > close, the kernel will eventually run out of RPC tags in devmnt. > > The issue is that syscalls get aborted when the process is dying. > these syscalls are ones in which the wait time is outside of the > kernel's control. qlocks, for instance, are okay. A kthread will > eventually get the lock and complete. rendez's get aborted. > > This doesn't play nicely with devmnt, which keeps retrying on abort. > but all syscalls abort for a DYING process, so it'll retry til we run > out of tags.
Ron suggested closing the FDT earlier in proc destroy. We can't do it while holding the spinlock, but perhaps earlier than that. We'd also need to block concurrent destroyers, which isn't a huge deal. There are other issues still. One of which is that the process is still running. Other threads on other cores may be trying to use those FDs and will flip out. What will the process do if FD 5 disappears? Write to FD 2, which is also gone? Then what.. spin? Trash memory? exit? The issue is that we don't want to start yanking out the FD table while the process is still running. 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). So here's the solution: We split the DYING state into DYING and DYING_ABORT. All code that cares about DYING now also cares about DYING and DYING_ABORT. Except for abort code, which only checks about DYING_ABORT. proc_destroy is mostly the same as it is now, with the addition of set_proc_state to DYING_ABORT *after* closing the FDT and before aborting all remaining syscalls. And there's a bunch of state checks that we'd need to change to accommodate the new state. Regarding this: > I'm not a huge fan of the infinite retry process. This is the "flush > the flush of the flush of the original op" deal, I think. Why does 9p > need so many flushes? Is one flush sufficient? Maybe, maybe not. In general, we can't allow the kernel to do unbounded things (work, memory, etc) that are controllable by something outside the kernel, whether that's userspace or a remote machine. Here are a couple examples in the area of devmnt of this problem: - We can't have devmnt (or any close operation) to wait indefinitely. Imagine a user process that is a 9p server that gets mounted. That process then opens one of its own FDs, then exits. Since it is exiting, it cannot respond to the close RPC. Devmnt needs some mechanism to abort (like timeouts, which might be somewhat in place). - The perpetual-flushing that mountio does for aborts needs to go too. Consider a user process that triggers a mountio with a syscall on one core, but then on another core it just constantly aborts that syscall (you can abort calls on other cores). If we got unlucky, we'd run out of RPC tags and crash devmnt. There are actually a lot of places in the kernel where this general rule (unbounded stuff) is broken. But let's fix these devmnt ones while we can. Barret -- 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.
