2.1. does ev_run() guarantee that no outstanding requests are alive or callbacks are pending on return?
On Thu, Mar 22, 2018 at 11:49 PM, CM <crusad...@gmail.com> wrote:
> 1. does libuv provide any guarantees wrt callback order in case when
> uv_close() cancels all outstanding requests on given handle -- i.e. can I
> rely that in close_cb all canceled requests callbacks have already been
> called?
Yes, request callbacks run before the close callback.
void my_coro(){
RingBuffer buf(1024);
SocketHandle sock(...); // in dtor it will call uv_close(), suspend and resume in uv_close callback...
// submit read/write requests that access 'buf' in their respective callbacks...
// here we hit an error and leave (via return or exception)
}
You should probably not rely on the order in which different request
types run, e.g., whether a connect callback comes before or after a
write callback.
> 2. can uv_close callback be cancelled or not completed? E.g. if I ask event
> loop to terminate -- will it wait for all callbacks to complete? what if
> these callbacks try to queue another requests -- will they get cancelled or
> those requests will fail to submit?
If "ask to terminate" means calling:
1. uv_stop() -> uv_stop() just tells uv_run() to return at its
earliest convenience, it doesn't shut down anything.
2. uv_loop_close() -> uv_loop_close() fails with UV_EBUSY if there are
active handles or requests.
A closing handle is considered active, even if it has been unref'd
with uv_unref().
When a callback creates another handle or request, it keeps the event
loop alive.
> 4. if I submit two write requests -- is it possible for first one to fail
> and for second one to succeed? (uv_tcp_t/uv_file_t/etc, Windows/Linux)
In theory, yes; in practice, no. Libuv stops reading and writing when
an I/O error happens. It is theoretically possible to start reading
and writing again if the error is transient, but in practice you
simply close the handle.
Same for uv_fs_t -- I can submit two write requests that will try to update different locations in the same file. If these writes are immediately "converted" to async/overlapped requests
> unless uv_close() keeps track of currently outstanding requests andLibuv keeps track of all outstanding requests (how else would it have known who to notify for completion)
> how to cleanly shutdown a running event loop?Libuv is designed for use from nodejs, which runs the event loop until all workers are closed and requests handed. To shutdown cleanly, wait for all outstanding requests to complete and then close all handles.
> What if during unwinding I will submit another request or try to open a new handle?You will have to decide how your application needs to handle this.Same for uv_fs_t -- I can submit two write requests that will try to update different locations in the same file. If these writes are immediately "converted" to async/overlapped requestsYes, there's a long-standing bug / PR that libuv sometimes assumes that fs writes simply can't fail: https://github.com/libuv/libuv/pull/269#discussion_r28131975
On Sun, Mar 25, 2018 at 2:05 PM, Jameson Nash <vtj...@gmail.com> wrote:> unless uv_close() keeps track of currently outstanding requests andLibuv keeps track of all outstanding requests (how else would it have known who to notify for completion)So, can I rely on uv_close callback to be invoked after all outstanding requests (on handle being closed) are canceled (and their callbacks are invoked)?
Also, this guarantee isn't very useful in context of coroutines. I.e. it guarantees that related couroutine(s) will resume before close_cb is called, but it won't guarantee that it will complete execution (and not suspend again). I.e. if your write/read/connect callback is used to resume a coroutine -- you probably better off adding explicit synchronization between your coroutine execution and related data structure destruction.