On Mon, Jul 6, 2020 at 8:34 AM Kenton Varda <ken...@cloudflare.com> wrote:
> On Mon, Jul 6, 2020 at 10:22 AM Vitali Lovich <vlov...@gmail.com> wrote: > >> I don't feel great about the duplication approach (or allowing retrieving >> the raw handle directly) as it can be subtly tricky to actually use >> correctly. For example, if you dup & make the dup'ed FD blocking, that will >> impact correct behavior within cap'n'proto. So as a user you'd end up >> wanting to always close the other FD after retrieving it. Since all usages >> have you invalidating the stream & consuming the FD, putting it in the >> provider is nice: it's symmetrical, you clearly have ownership of the >> stream, and it's a natural spot to have flags to automatically make the >> socket/FD blocking again. >> > > I think there are a lot of use cases where you wouldn't want to destroy > the AsyncIoStream object, though. For example, if I have a web server > that's serving a file from disk, it might call getFd() so that it can use > sendfile() to push bytes out without copying through userspace. But the > stream can be reused for another HTTP request after that, so it can't be > destroyed in the meantime. > > Hmm, in fact, for this use case it seems like the web server has to be > able to get the FD *and* the UnixEventPort::FdObserver object together, so > that it can use the latter to observe when the socket is writable. That's a > bit of a problem since FdObserver is currently specific to UnixEventPort; > when using something like the libuv compatibility layer in node-capnp, this > wouldn't work. Maybe the answer is to define an FdObserver abstract > interface. At least the way sockets work is pretty consistent across unix > variants. (On Windows, of course, something entirely different is needed... > but that was already true.) > > I don't like requiring an AsyncIoProvider to unwrap because it's generally > uncommon to pass the AsyncIoProvider down into libraries. I think these > kinds of optimizations should be possible to implement without requiring > the library to take whole new, wide interfaces. > That's fair but I think the problem of weakly obtaining the FD still has a lot of pitfalls. Even if you return all the things you need, you potentially have scheduled I/O in-flight (e.g. you may be pumping the FD). So you need a way to plug it or your sendfile will crap out unless you're doing it in-situ of the KJ loop (i.e. you can't defer the sendfile to a background thread & continue to process any remaining I/O). Co-ordinating all of that could be pretty tricky. I think a potential middle ground for this might be to have the stream give you the fd and a fulfiller. Any I/O operations on the stream then are blocked from executing until after the promise to return the FD is fulfilled. I don't think the WebServer would need an FdObserver because you could return the FD in blocking mode & the user could dispatch the I/O to a background thread & get back onto the executor to fulfill the promise once complete. Not like sendfile and non-blocking interact all that well. I don't know how to tackle the library problem for the interface but I also don't have any experience to understand how such libraries are written. The way I've structured all of my libraries is that either it's owning the cap'n'proto loop as an implementation detail running on its own thread OR it's dealing with implementing the capability & thus the low-level I/O generally doesn't come up (although maybe it does if you're shuttling FDs around - I haven't gotten to that point yet). I think for the simple use-cases consuming the Stream is the correct option as it will end up crashing if you have any in-flight promises (& lifting that restriction would have to be a requirement for doing so in the above case). So it feels like a straightforward QOL addition to AsyncIoProvider with minimal complexity & the richer, more powerful API with the streams themselves could be done separately focusing on all the nuances of how it should behave. > -Kenton > >> -- You received this message because you are subscribed to the Google Groups "Cap'n Proto" group. To unsubscribe from this group and stop receiving emails from it, send an email to capnproto+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/capnproto/CAF8PYMgpCLoRe5XwWO1r%2BBFVKzk_Pr_Egxx%2BpPLScm6qSeQQaw%40mail.gmail.com.