Is it really done when you call tevent_req_done?

Stefan (metze) Metzmacher metze at
Sat Jan 24 09:52:30 MST 2015

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
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

In some situations tevent_req_done() (, tevent_req_notify_callback() or
doesn't call the callers callback function:
1. when it's called from the _send() function or
2. when tevent_req_defer_callback() was called.

In these cases a tevent_immediate event will retry
to trigger the callback.

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...


-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 181 bytes
Desc: OpenPGP digital signature
URL: <>

More information about the samba-technical mailing list