Is it really done when you call tevent_req_done?
Richard Sharpe
realrichardsharpe at gmail.com
Sat Jan 24 10:36:45 MST 2015
On Sat, Jan 24, 2015 at 8:52 AM, Stefan (metze) Metzmacher
<metze at samba.org> wrote:
> Hi Richard,
>
>> In my seemingly never ending quest to understand tevent, I noticed the
>> following in some random smb2 request processing routine, like
>> smbd_smb2_request_process_tcon:
>>
>> ....
>>
>> subreq = smbd_smb2_tree_connect_send(req,
>> req->sconn->ev_ctx,
>> req,
>> in_path_string);
>> if (subreq == NULL) {
>> return smbd_smb2_request_error(req, NT_STATUS_NO_MEMORY);
>> }
>> tevent_req_set_callback(subreq, smbd_smb2_request_tcon_done, req);
>>
>> return smbd_smb2_request_pending_queue(req, subreq, 500);
>>
>> So, we create a subrequest in smbd_smb2_tree_connect_send and if we
>> got one, we set a callback (smbd_smb2_request_tcon_done and then call
>> that routine that will queue it perhaps.
>>
>> However, when we look at smbd_smb2_tree_connect_send we see:
>>
>> ...
>> status = smbd_smb2_tree_connect(smb2req,
>> state->in_path,
>> &state->out_share_type,
>> &state->out_share_flags,
>> &state->out_capabilities,
>> &state->out_maximal_access,
>> &state->out_tree_id);
>> if (tevent_req_nterror(req, status)) {
>> return tevent_req_post(req, ev);
>> }
>>
>> tevent_req_done(req);
>> return tevent_req_post(req, ev);
>>
>> Huh, is it done or what? Done means finito, no more to do, etc. But
>> seemingly the request has a second life because tevent_req_post is
>> going to stick it in the tevent queue and then when we get back to our
>> caller it is going to be given a callback ...
>>
>> I am confused and starting to feel like Alice:
>>
>> 'When I use a word,' Humpty Dumpty said, in rather a scornful tone,
>> 'it means just what I choose it to mean — neither more nor less.'
>
> There three layers:
>
> 1. The implementation e.g. all smbd_smb2_tree_connect* functions.
> The implementation provides a _send() and a _recv() function
> to the callers. The implementation owns the internal
> smbd_smb2_tree_connect_state.
> 2. The tevent_req* helper functions.
> 3. The caller, it offers the memory context and event context
> and passes them to the _send() function. The sync caller
> checks tevent_req_is_in_progress() is false before calling
> the _recv() function to get the result. An async caller
> calls the _recv() function from a registered callback function.
> The caller owns the 'tevent_req' structure and should free it
> after calling the _recv() function.
>
> So from the implementation ("smbd_smb2_tree_connect*") point of view
> the work that needs to be done is done.
> At this point tevent_req_is_in_progress()
> would return false.
>
> That means that the caller can ask for result by calling
> smbd_smb2_tree_connect_recv().
>
> In some situations tevent_req_done() (, tevent_req_notify_callback() or
> tevent_req_*error())
> doesn't call the callers callback function:
> 1. when it's called from the _send() function or
Hmmm, but that seems to be because no callback function has been
established yet via tevent_req_set_callback.
> 2. when tevent_req_defer_callback() was called.
>
> In these cases a tevent_immediate event will retry
> to trigger the callback.
Right, but that seems to be caused by the tevent_req_post call that is
made, and the callback is not established until we are out of the
context of the caller of tevent_req_post.
> Once the caller gets the result using the _recv() function
> it can use destroy the request by using TALLOC_FREE(subreq).
>
> I hope this explains it a bit...
Yes, it does. I know this stuff is cast in stone now, but the naming
of some of the helper functions obfuscates things quite a bit.
> metze
>
--
Regards,
Richard Sharpe
(何以解憂?唯有杜康。--曹操)
More information about the samba-technical
mailing list