Uh oh!
There was an error while loading. Please reload this page.
Fix context in protocol callbacks - #348
Conversation
1st1
commented
May 25, 2020
My memory here is a little rusty, but can we instead change Lines 338 to 421 in 465717f |
fantix
commented
May 26, 2020
Maybe yes - they're intended to bridge the native callbacks anyways, right? Submitted a commit to try this approach. I had to hack in the |
1st1
commented
May 26, 2020
I think we need parallel APIs like |
1st1
commented
May 26, 2020
Or add a trailing argument to all |
fantix
commented
May 26, 2020
Got it, that makes sense - I'll then try to propose something more complete. |
fantix
commented
Dec 13, 2020
/me is trying to fix this one now. |
1st1
commented
Dec 15, 2020
Nice, what's the latest? ;) |
| | +- UnixServer (pipe) | ||
| +- UVTimer (timer) | ||
| """ | ||
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
70b6ae4 to
81d3900Compare6f41c33 to
e9b4056CompareThis is a combined fix to correct contexts from which protocal callbacks are invoked. In short, callbacks like data_received() should always be invoked from consistent contexts which are copied from the context where the underlying UVHandle is created or started. The new test case covers also asyncio, but skipping the failing ones.
A quick recap of uvloop core:
Loopis the uvloop-version of an asyncio event loop, exposing APIs to createUVHandles like TCP transports.UVHandleis the base class of uvloop wrappers of the libuvuv_handle_tstructs, see the full family below.UVHandlereferencesonezero or moreHandleinstances that encapsulate the actual callback, its arguments, and a PEP-567 context.cdeffunction perUVHandlethat is registered to the libuvuv_handle_tstruct. This function usually just triggers running theHandle.UVHandleusesHandlefor callbacks, and we don't want to change that.What is missing is e.g. thelisten_handleof someUVHandlesubclasses like theUVStreamServer. For now, it calls the actual callback (_on_listen) directly without PEP-567 context. So this PR should add those missingHandles.The tricky part is, the currentHandlesupports only fixed parameters provided at initialization, what is needed for callbacks like_on_listenor__uv_stream_on_readis a partial-likeHandle._run_with_param().List of
UVHandles to check:UVAsyncUVCheckUVIdleUVPollUVProcessUVProcessTransportUDPTransportUVStreamUVStreamServerUVTimerPrincipals
UVHandleinstance (including transports, servers, etc) sticks to one context where it was created from and/or started to take effect.UVHandle(mostly protocol callbacks, but also protocol factory) runs in the same context.UVHandleinstances share the same context - for example, protocol callbacks are always called in the same context even though the transport is upgraded bystart_tls()in a different context (even multiple times, a.k.a. SSL over SSL).Contextinstance - it can be a copied instance. Therefore, changes to aContextVarare not always carried between different protocol callbacks. But all callbacks could see the same inherited value from the context where theUVHandlewas created or started.Context.copy()orcopy_context()in user-triggered events, and reuse existingContextinstances for uvloop-triggered events, so as to avoid re-entering the same context twice.copy_context()is only applied to direct method calls, callbacks through e.g.loop.call_soon()are not considered necessary to copy the context.Example 1: Client Protocol
Expected result:
Example 2: Server Protocol
Expected result:
Example 3:
start_servingSimilar to example 2, but start serving in a different context:
Expected result:
Example 4: TLS Upgrade
Expected result: