tevent_request(3)
π tevent_request(3) β NAME π
okay so this is tevent_request(3) from the Library Functions Manual, and it's literally the whole lore of tevent requests π¦
tevent_request β The tevent request functions, bestie. β¨
- A
tevent_reqrepresents an asynchronous computation. periodt.
β¨ SYNOPSIS β¨
π Topics
The tevent helper functions π«Ά
π Typedefs
typedef void(* tevent_req_fn) (struct tevent_req *subreq)β A tevent request callback function. πtypedef char *(* tevent_req_print_fn) (struct tevent_req *req, TALLOC_CTX *ctx)β The print function which can be set for a tevent async request.typedef bool(* tevent_req_cancel_fn) (struct tevent_req *req)β A typedef for a cancel function for a tevent request.typedef void(* tevent_req_cleanup_fn) (struct tevent_req *req, enum tevent_req_state req_state)β A typedef for a cleanup function for a tevent request.
π Enumerations
enum tevent_req_state { TEVENT_REQ_INIT, TEVENT_REQ_IN_PROGRESS, TEVENT_REQ_DONE, TEVENT_REQ_USER_ERROR, TEVENT_REQ_TIMED_OUT, TEVENT_REQ_NO_MEMORY, TEVENT_REQ_RECEIVED }β An async request moves fromTEVENT_REQ_INITtoTEVENT_REQ_IN_PROGRESS. π
π Functions
void tevent_req_set_callback (struct tevent_req *req, tevent_req_fn fn, void *pvt)β Set an async request callback. πΈvoid * tevent_req_callback_data (struct tevent_req *req, #type)β Get the private data cast to the given type for a callback from a tevent request structure.void * tevent_req_callback_data_void (struct tevent_req *req)β Get the private data for a callback from a tevent request structure.void * tevent_req_data (struct tevent_req *req, #type)β Get the private data from a tevent request structure.void tevent_req_set_print_fn (struct tevent_req *req, tevent_req_print_fn fn)β This function sets a print function for the given request.char * tevent_req_default_print (struct tevent_req *req, TALLOC_CTX *mem_ctx)β The default print function for creating debug messages.char * tevent_req_print (TALLOC_CTX *mem_ctx, struct tevent_req *req)β Print antevent_reqstructure in debug messages.void tevent_req_set_cancel_fn (struct tevent_req *req, tevent_req_cancel_fn fn)β This function sets a cancel function for the given tevent request.bool tevent_req_cancel (struct tevent_req *req)β Try to cancel the given tevent request.void tevent_req_set_cleanup_fn (struct tevent_req *req, tevent_req_cleanup_fn fn)β This function sets a cleanup function for the given tevent request.struct tevent_req * tevent_req_create (TALLOC_CTX *mem_ctx, void **pstate, #type)β Create an async tevent request.bool tevent_req_set_endtime (struct tevent_req *req, struct tevent_context *ev, struct timeval endtime)β Set a timeout for an async request. β°void tevent_req_reset_endtime (struct tevent_req *req)β Reset the timer set bytevent_req_set_endtime.void tevent_req_notify_callback (struct tevent_req *req)β Call the notify callback of the given tevent request manually.void tevent_req_done (struct tevent_req *req)β An async request has successfully finished. πbool tevent_req_error (struct tevent_req *req, uint64_t error)β An async request has seen an error. πbool tevent_req_nomem (const void *p, struct tevent_req *req)β Helper function for nomem check.void tevent_req_oom (struct tevent_req *req)β Indicate out of memory to a request.struct tevent_req * tevent_req_post (struct tevent_req *req, struct tevent_context *ev)β Finish a request before the caller had a chance to set the callback.void tevent_req_defer_callback (struct tevent_req *req, struct tevent_context *ev)β Finish multiple requests within one function.bool tevent_req_is_in_progress (struct tevent_req *req)β Check if the given request is still in progress.bool tevent_req_poll (struct tevent_req *req, struct tevent_context *ev)β Actively poll for the given request to finish.bool tevent_req_is_error (struct tevent_req *req, enum tevent_req_state *state, uint64_t *error)β Get the tevent request state and the actual error set bytevent_req_error.void tevent_req_received (struct tevent_req *req)β Use as the last action of a_recv()function.bool tevent_req_set_profile (struct tevent_req *req)β Mark atevent_reqfor profiling.const struct tevent_req_profile * tevent_req_get_profile (struct tevent_req *req)β Get a request's profile for inspection.struct tevent_req_profile * tevent_req_move_profile (struct tevent_req *req, TALLOC_CTX *mem_ctx)β Move the profile out of a request.void tevent_req_profile_get_name (const struct tevent_req_profile *profile, const char **req_name)β Get a profile description.void tevent_req_profile_get_start (const struct tevent_req_profile *profile, const char **start_location, struct timeval *start_time)β Get a profile's start event data.void tevent_req_profile_get_stop (const struct tevent_req_profile *profile, const char **stop_location, struct timeval *stop_time)β Get a profile's stop event data.void tevent_req_profile_get_status (const struct tevent_req_profile *profile, pid_t *pid, enum tevent_req_state *state, uint64_t *user_error)β Get a profile's result data.const struct tevent_req_profile * tevent_req_profile_get_subprofiles (const struct tevent_req_profile *profile)β Retrieve the first subreq's profile from a profile.const struct tevent_req_profile * tevent_req_profile_next (const struct tevent_req_profile *profile)β Walk the chain of subreqs.struct tevent_req_profile * tevent_req_profile_create (TALLOC_CTX *mem_ctx)β Create a freshtevent_req_profile.bool tevent_req_profile_set_name (struct tevent_req_profile *profile, const char *name)β Set a profile's name.bool tevent_req_profile_set_start (struct tevent_req_profile *profile, const char *start_location, struct timeval start_time)β Set a profile's start event.bool tevent_req_profile_set_stop (struct tevent_req_profile *profile, const char *stop_location, struct timeval stop_time)β Set a profile's stop event.void tevent_req_profile_set_status (struct tevent_req_profile *profile, pid_t pid, enum tevent_req_state state, uint64_t user_error)β Set a profile's exit status.void tevent_req_profile_append_sub (struct tevent_req_profile *parent_profile, struct tevent_req_profile **sub_profile)β Add a subprofile to a profile.struct tevent_req * tevent_wakeup_send (TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct timeval wakeup_time)β Create a tevent subrequest at a given time. πbool tevent_wakeup_recv (struct tevent_req *req)β Check if the wakeup has been correctly executed.
π Detailed Description π
A tevent_req represents an asynchronous computation. fr fr. π«
The tevent_req group of API calls is the recommended way of programming async computations within tevent. In particular the file descriptor (tevent_add_fd) and timer (tevent_add_timed) events are considered too low-level to be used in larger computations. To read and write from and to sockets, Samba provides two calls on top of tevent_add_fd: tstream_read_packet_send/recv and tstream_writev_send/recv. These requests are much easier to compose than the low-level event handlers called from tevent_add_fd. slay. π
A lot of the simplicity tevent_req has brought to the notoriously hairy async programming came via a set of conventions that every async computation programmed should follow. One central piece of these conventions is the naming of routines and variables. π
Every async computation needs a name (sensibly called "computation" down from here). From this name quite a few naming conventions are derived.
Every computation that requires local state needs a:
struct computation_state {
int local_var;
};
Even if no local variables are required, such a state struct should be created containing a dummy variable. Quite a few helper functions and macros (for example tevent_req_create()) assume such a state struct. no cap. π«Ά
An async computation is started by a computation_send function. When it is finished, its result can be received by a computation_recv function. For an example how to set up an async computation, see the code example in the documentation for tevent_req_create() and tevent_req_post(). The prototypes for _send and _recv functions should follow some conventions:
struct tevent_req *computation_send(TALLOC_CTX *mem_ctx,
struct tevent_context *ev,
... further args);
int computation_recv(struct tevent_req *req, ... further output args);
The "int" result of computation_recv() depends on the result the sync version of the function would have, "int" is just an example here. π
Another important piece of the conventions is that the program flow is interrupted as little as possible. Because a blocking sub-computation requires that the flow needs to continue in a separate function that is the logical sequel of some computation, it should lexically follow sending off the blocking sub-computation. Setting the callback function via tevent_req_set_callback() requires referencing a function lexically below the call to tevent_req_set_callback(), forward declarations are required. A lot of the async computations thus begin with a sequence of declarations such as:
static void computation_step1_done(struct tevent_req *subreq);
static void computation_step2_done(struct tevent_req *subreq);
static void computation_step3_done(struct tevent_req *subreq);
It really helps readability a lot to do these forward declarations, because the lexically sequential program flow makes the async computations almost as clear to read as a normal, sync program flow. iconic honestly. β¨
It is up to the user of the async computation to talloc_free it after it has finished. If an async computation should be aborted, the tevent_req structure can be talloc_free'ed. After it has finished, it should talloc_free'ed by the API user. π§
tevent_req variable naming conventions:
The name of the variable pointing to the tevent_req structure returned by a _send() function SHOULD be named differently between implementation and caller.
From the point of view of the implementation (of the _send() and _recv() functions) the variable returned by tevent_req_create() is always called req.
While the caller of the _send() function should use subreq to hold the result. π
See also
tevent_req_create()tevent_req_fn()
Typedef Documentation π
typedef bool(*tevent_req_cancel_fn) (struct tevent_req *req)
okay so this is a typedef for a cancel function for a tevent request β¨
reqβ The tevent request calling this function.
Returns: True if the request could be canceled, false if not. π«Ά
typedef void(*tevent_req_cleanup_fn) (struct tevent_req *req, enum tevent_req_state req_state)
a typedef for a cleanup function for a tevent request π§Ή
reqβ The tevent request calling this function.req_stateβ The currenttevent_req_state.
typedef void(*tevent_req_fn) (struct tevent_req *subreq)
A tevent request callback function. yep, that's the whole vibe π
subreqβ The tevent async request which executed this callback.
typedef char *(*tevent_req_print_fn) (struct tevent_req *req, TALLOC_CTX *ctx)
The print function which can be set for a tevent async request π¨οΈ
reqβ The tevent async request.ctxβ A talloc memory context which can be uses to allocate memory.
Returns: An allocated string buffer to print.
Example:
static char *my_print(struct tevent_req *req, TALLOC_CTX *mem_ctx)
{
struct my_data *data = tevent_req_data(req, struct my_data);
char *result;
result = tevent_req_default_print(mem_ctx, req);
if (result == NULL) {
return NULL;
}
return talloc_asprintf_append_buffer(result, "foo=%d, bar=%d",
data->foo, data->bar);
}
Enumeration Type Documentation π
enum tevent_req_state
An async request moves from TEVENT_REQ_INIT to TEVENT_REQ_IN_PROGRESS. All other states are valid after a request has finished. like, it's got β¨phasesβ¨ bestie.
Enumerator:
TEVENT_REQ_INITβ We are creating the request. π£TEVENT_REQ_IN_PROGRESSβ We are waiting the request to complete. β³TEVENT_REQ_DONEβ The request is finished successfully. πTEVENT_REQ_USER_ERRORβ A user error has occurred. The user error has been indicated bytevent_req_error(), it can be retrieved viatevent_req_is_error(). πTEVENT_REQ_TIMED_OUTβ Request timed out after the timeout set bytevent_req_set_endtime. βTEVENT_REQ_NO_MEMORYβ An internal allocation has failed, ortevent_req_nomemhas been given aNULLpointer as the first argument. πTEVENT_REQ_RECEIVEDβ The request has been received by the caller. No further action is valid. π
Function Documentation π
void * tevent_req_callback_data (struct tevent_req * req, # type)
Get the private data cast to the given type for a callback from a tevent request structure. it's giving "gimme my stuff back, but typed" π
static void computation_done(struct tevent_req *subreq) {
struct tevent_req *req = tevent_req_callback_data(subreq, struct tevent_req);
struct computation_state *state = tevent_req_data(req, struct computation_state);
.... more things, eventually maybe call tevent_req_done(req);
}
reqβ The structure to get the callback data from.typeβ The type of the private callback data to get.
Returns: The type casted private data set NULL if not set. π«Ά
void * tevent_req_callback_data_void (struct tevent_req * req)
Get the private data for a callback from a tevent request structure. no type gymnastics this time, just vibes π¦
reqβ The structure to get the callback data from.
Returns: The private data or NULL if not set.
bool tevent_req_cancel (struct tevent_req * req)
Try to cancel the given tevent request. This function can be used to cancel the given request. β
It is only possible to cancel a request when the implementation has registered a cancel function via the tevent_req_set_cancel_fn().
reqβ The request to use.
Returns: This function returns true if the request is cancelable, otherwise false is returned.
Note: Even if the function returns true, the caller need to wait for the function to complete normally. Only the _recv() function of the given request indicates if the request was really canceled. so like, true does NOT mean "it's gone", bestie π
struct tevent_req * tevent_req_create (TALLOC_CTX * mem_ctx, void ** pstate, # type)
Create an async tevent request. The new async request will be initialized in state TEVENT_REQ_IN_PROGRESS. β¨ the origin story β¨
struct tevent_req *req;
struct computation_state *state;
req = tevent_req_create(mem_ctx, &state, struct computation_state);
Tevent_req_create() allocates and zeros the state variable as a talloc child of its result. The state variable should be used as the talloc parent for all temporary variables that are allocated during the async computation. This way, when the user of the async computation frees the request, the state as a talloc child will be free'd along with all the temporary variables hanging off the state. π§Ήβ¨ everything goes down together, no strays.
mem_ctxβ The memory context for the result.pstateβ Pointer to the private request state.typeβ The name of the request.
Returns: A new async request. NULL on error.
void * tevent_req_data (struct tevent_req * req, # type)
Get the private data from a tevent request structure. When the tevent_req has been created by tevent_req_create, the result of tevent_req_data() is the state variable created by tevent_req_create() as a child of the req. π
reqβ The structure to get the private data from.typeβ The type of the private data
Returns: The private data or NULL if not set.
char * tevent_req_default_print (struct tevent_req * req, TALLOC_CTX * mem_ctx)
The default print function for creating debug messages. The function should not be used by users of the async API, but custom print function can use it and append custom text to the string. π
reqβ The request to be printed.mem_ctxβ The memory context for the result.
Returns: Text representation of request.
void tevent_req_defer_callback (struct tevent_req * req, struct tevent_context * ev)
Finish multiple requests within one function. Normally tevent_req_notify_callback() and all wrappers (e.g. tevent_req_done() and tevent_req_error()) need to be the last thing an event handler should call. This is because the callback is likely to destroy the context of the current function. π¬ like walking out of the room mid-sentence.
If a function wants to notify more than one caller, it is dangerous if it just triggers multiple callbacks in a row. With tevent_req_defer_callback() it is possible to set an event context that will be used to defer the callback via an immediate event (similar to tevent_req_post()). π«Ά
struct complete_state {
struct tevent_context *ev;
struct tevent_req **reqs;
};
void complete(struct complete_state *state)
{
size_t i, c = talloc_array_length(state->reqs);
for (i=0; i < c; i++) {
tevent_req_defer_callback(state->reqs[i], state->ev);
tevent_req_done(state->reqs[i]);
}
}
reqβ The finished request.evβ The tevent_context for the immediate event.
Returns: The given request will be returned.
void tevent_req_done (struct tevent_req * req)
An async request has successfully finished. π This function is to be used by implementors of async requests. When a request is successfully finished, this function calls the user's completion function.
reqβ The finished request.
bool tevent_req_error (struct tevent_req * req, uint64_t error)
An async request has seen an error. π This function is to be used by implementors of async requests. When a request can not successfully completed, the implementation should call this function with the appropriate status code.
If error is 0 the function returns false and does nothing more. π«
reqβ The request with an error.errorβ The error code.
Returns: On success true is returned, false if error is 0.
int error = first_function();
if (tevent_req_error(req, error)) {
return;
}
error = second_function();
if (tevent_req_error(req, error)) {
return;
}
tevent_req_done(req);
return;
const struct tevent_req_profile * tevent_req_get_profile (struct tevent_req * req)
Get a request's profile for inspection. π getting the receipts, basically.
reqβ The request to get the profile from
Returns: The request's profile
bool tevent_req_is_error (struct tevent_req * req, enum tevent_req_state * state, uint64_t * error)
Get the tevent request state and the actual error set by tevent_req_error. π«Ά
int computation_recv(struct tevent_req *req, uint64_t *perr)
{
enum tevent_req_state state;
uint64_t err;
if (tevent_req_is_error(req, &state, &err)) {
*perr = err;
return -1;
}
return 0;
}
reqβ The tevent request to get the error from.stateβ A pointer to store the tevent request error state.errorβ A pointer to store the error set bytevent_req_error().
Returns: True if the function could set error and state, false otherwise.
See also: tevent_req_error()
bool tevent_req_is_in_progress (struct tevent_req * req)
Check if the given request is still in progress. It is typically used by sync wrapper functions. β³
reqβ The request to poll.
Returns: The boolean form of "is in progress".
struct tevent_req_profile * tevent_req_move_profile (struct tevent_req * req, TALLOC_CTX * mem_ctx)
Move the profile out of a request. This function detaches the request's profile from the request, so that the profile can outlive the request in a _recv function. π it gets to live on, iconic.
reqβ The request to move the profile out ofmem_ctxβ The new talloc context for the profile
Returns: The moved profile
bool tevent_req_nomem (const void * p, struct tevent_req * req)
Helper function for nomem check. Convenience helper to easily check alloc failure within a callback implementing the next step of an async request. π
pβ The pointer to be checked.reqβ The request being processed.
p = talloc(mem_ctx, bla);
if (tevent_req_nomem(p, req)) {
return;
}
void tevent_req_notify_callback (struct tevent_req * req)
Call the notify callback of the given tevent request manually. π
reqβ The tevent request to call the notify function from.
See also: tevent_req_set_callback()
void tevent_req_oom (struct tevent_req * req)
Indicate out of memory to a request. π no memory, no vibes.
reqβ The request being processed.
bool tevent_req_poll (struct tevent_req * req, struct tevent_context * ev)
Actively poll for the given request to finish. This function is typically used by sync wrapper functions. π
reqβ The request to poll.evβ The tevent_context to be used.
Returns β bestie, on success you get true back π. But if something truly critical went down in the tevent loop layer, you get false instead. And listen β that is not the return value of the request you passed in, don't even play π.
Note β only reach for this if the tevent_context was created by you, the caller. It's to avoid event loop nesting, iykyk.
req = tstream_writev_queue_send(mem_ctx,
ev_ctx,
tstream,
send_queue,
iov, 2);
ok = tevent_req_poll(req, tctx->ev);
rc = tstream_writev_queue_recv(req, &sys_errno);
TALLOC_FREE(req);
struct tevent_req * tevent_req_post (struct tevent_req * req, struct tevent_context * ev)
Finish a request before the caller even got a chance to set the callback. β¨
Here's the vibe: an async request implementation might realize it can finish the whole thing without waiting on any external event β or it can't even start the engine π« . To keep up the illusion of a callback for the API user, the implementation can call this helper function, which fires off an immediate event. That way the caller can use the exact same calling conventions, no matter whether the request was actually deferred or not. Iconic behavior honestly π
struct tevent_req *computation_send(TALLOC_CTX *mem_ctx,
struct tevent_context *ev)
{
struct tevent_req *req, *subreq;
struct computation_state *state;
req = tevent_req_create(mem_ctx, &state, struct computation_state);
if (req == NULL) {
return NULL;
}
subreq = subcomputation_send(state, ev);
if (tevent_req_nomem(subreq, req)) {
return tevent_req_post(req, ev);
}
tevent_req_set_callback(subreq, computation_done, req);
return req;
}
Parameters
reqβ the finished request, periodt.evβ thetevent_contextfor that immediate event.
Returns β the given request will be handed right back to you, no cap π .
char * tevent_req_print (TALLOC_CTX * mem_ctx, struct tevent_req * req)
Prints a tevent_req structure into debug messages π. This one is meant for callers of the async API to use.
Parameters
mem_ctxβ the memory context for the result.reqβ the request you wanna print.
Returns β a text representation of the request β¨.
void tevent_req_profile_append_sub (struct tevent_req_profile * parent_profile, struct tevent_req_profile ** sub_profile)
Adds a subprofile to a profile π.
Parameters
parent_profileβ the profile that's getting modified.sub_profileβ the subreq's profile profile that's getting added.
Also, heads up: "subreq" is talloc_move'ed into "parent_profile", so the talloc ownership of "sub_profile" changes π.
struct tevent_req_profile * tevent_req_profile_create (TALLOC_CTX * mem_ctx)
Creates a fresh tevent_req_profile πΈ.
Parameters
mem_ctxβ the talloc context to hang the fresh struct off of.
Returns β the fresh struct, bestie π«Ά.
void tevent_req_profile_get_name (const struct tevent_req_profile * profile, const char ** req_name)
Grabs a profile's description π·οΈ.
Parameters
profileβ the profile you're querying.req_nameβ the name of the request (that's the state's name).
And note: "req_name" after this call is still in talloc-posession of "profile" π.
void tevent_req_profile_get_start (const struct tevent_req_profile * profile, const char ** start_location, struct timeval * start_time)
Grabs a profile's start event data β±οΈ.
Parameters
profileβ the profile you're querying.start_locationβ where this event started.start_timeβ when this event started.
Also: "start_location" after this call is still in talloc-posession of "profile" π.
void tevent_req_profile_get_status (const struct tevent_req_profile * profile, pid_t * pid, enum tevent_req_state * state, uint64_t * user_error)
Grabs a profile's result data π.
Parameters
pidβ the process where this profile was taken.stateβ the status the profile'stevent_reqfinished with.user_errorβ the user error of the profile'stevent_req.
void tevent_req_profile_get_stop (const struct tevent_req_profile * profile, const char ** stop_location, struct timeval * stop_time)
Grabs a profile's stop event data π.
Parameters
profileβ the profile you're querying.stop_locationβ where this event stopped.stop_timeβ when this event stopped.
And again: "stop_location" after this call is still in talloc-posession of "profile" π.
const struct tevent_req_profile * tevent_req_profile_get_subprofiles (const struct tevent_req_profile * profile)
Pulls the first subreq's profile out of a profile π¦.
Parameters
profileβ the profile to query.
Returns β the first tevent subreq's profile β¨.
const struct tevent_req_profile * tevent_req_profile_next (const struct tevent_req_profile * profile)
Walks the chain of subreqs, one by one π.
Parameters
profileβ the subreq's profile to walk.
Returns β the next subprofile in the list π .
bool tevent_req_profile_set_name (struct tevent_req_profile * profile, const char * name)
Sets a profile's name π·οΈ.
Parameters
profileβ the profile to set the name for.nameβ the new name for the profile.
Returns β True if the internal talloc_strdup succeeded β
.
bool tevent_req_profile_set_start (struct tevent_req_profile * profile, const char * start_location, struct timeval start_time)
Sets a profile's start event β±οΈ.
Parameters
profileβ the profile to set the start data for.start_locationβ the new start location.start_timeβ the new start time.
Returns β True if the internal talloc_strdup succeeded β
.
void tevent_req_profile_set_status (struct tevent_req_profile * profile, pid_t pid, enum tevent_req_state state, uint64_t user_error)
Sets a profile's exit status π¦.
Parameters
profileβ the profile to set the exit status for.pidβ the process where this profile was taken.stateβ the status the profile'stevent_reqfinished with.user_errorβ the user error of the profile'stevent_req.
bool tevent_req_profile_set_stop (struct tevent_req_profile * profile, const char * stop_location, struct timeval stop_time)
Sets a profile's stop event π.
Parameters
profileβ the profile to set the stop data for.stop_locationβ the new stop location.stop_timeβ the new stop time.
Returns β True if the internal talloc_strdup succeeded β
.
void tevent_req_received (struct tevent_req * req)
Use this as the last action of a _recv() function π«‘. It destroys the attached private data.
Parameters
reqβ the finished request.
void tevent_req_reset_endtime (struct tevent_req * req)
Resets the timer that was set by tevent_req_set_endtime β²οΈ.
Parameters
reqβ the request to reset the timeout for.
void tevent_req_set_callback (struct tevent_req * req, tevent_req_fn fn, void * pvt)
Sets an async request callback π. Wanna see how it's supposed to be used? Go peek at the docs of tevent_req_post() for an example.
Parameters
reqβ the async request to set the callback on.fnβ the callback function to set.pvtβ a pointer to private data to pass to the async request callback.
void tevent_req_set_cancel_fn (struct tevent_req * req, tevent_req_cancel_fn fn)
This sets a cancel function for the given tevent request π«. You can use it to set up a cancel function for the request you're holding. It gets triggered whenever the tevent_req_cancel() function is called on that given request.
Parameters
reqβ the request to use.fnβ a pointer to the cancel function.
void tevent_req_set_cleanup_fn (struct tevent_req * req, tevent_req_cleanup_fn fn)
This sets a cleanup function for the given tevent request π§Ή. You can use it to set up a cleanup function for that request. It gets triggered when the tevent_req_done() or tevent_req_error() function was called β before notifying the caller's callback function, and also before scheduling the deferred trigger.
Super useful if more than one tevent_req belong together and need to finish both requests at the same time π«Ά.
The cleanup function is able to call tevent_req_done() or tevent_req_error() recursively β but the cleanup function is only triggered the first time π.
The cleanup function is also called by tevent_req_received() (possibly triggered from tevent_req_destructor()) before destroying the private data of the tevent_req π.
Parameters
reqβ the request to use.fnβ a pointer to the cancel function.
bool tevent_req_set_endtime (struct tevent_req * req, struct tevent_context * ev, struct timeval endtime)
Sets a timeout for an async request β°. Heads up: on failure, "req" is already set to state TEVENT_REQ_NO_MEMORY.
Parameters
reqβ the request to set the timeout for.evβ the event context to use for the timer.endtimeβ the endtime of the request.
Returns β True if it succeeded, false if not.
void tevent_req_set_print_fn (struct tevent_req * req, tevent_req_print_fn fn)
This sets a print function for the given request π¨οΈ. You can use it to set up a print function for that request. It gets triggered whenever the tevent_req_print() function is called on the given request.
Parameters
reqβ the request to use.fnβ a pointer to the print function.
Note β this function should only be used for debugging π. Fr fr.
bool tevent_req_set_profile (struct tevent_req * req)
Marks a tevent_req for profiling π. This turns on profiling for this tevent_req and all subreqs that are directly started as helper requests off of this tevent_req. The subreqs get chained by walking up the talloc_parent hierarchy at a subreq's tevent_req_create. Which means β to get the profiling chain right, the subreq that needs to be profiled as part of this tevent_req's profile must be a talloc child of the request's state variable, okurrr? π
Parameters
reqβ the request to do tracing for.
Returns β False if the profile could not be activated π.
bool tevent_wakeup_recv (struct tevent_req * req)
Checks if the wakeup has been correctly executed β
. This function needs to be called in the callback function set after calling tevent_wakeup_send().
Parameters
reqβ the tevent request to check.
Returns β True on success, false otherwise.
See also β tevent_wakeup_recv()
struct tevent_req * tevent_wakeup_send (TALLOC_CTX * mem_ctx, struct tevent_context * ev, struct timeval wakeup_time)
Creates a tevent subrequest at a given time β°. The whole idea is that there's always the same syntax for tevent requests, bestie. Consistency slay β¨.
Parameters
mem_ctxβ the talloc memory context to use.evβ the event handle to setup the request.wakeup_timeβ the time to wakeup and execute the request.
Returns β the new subrequest, or NULL on error π.
Example:
Okay so picture this: you're chillin' inside a callback, and the move is to tevent_wakeup_send() a subrequest and then wait for it to come back. Here's the whole vibe, bestie π
static void my_callback_wakeup_done(tevent_req *subreq)
{
struct tevent_req *req = tevent_req_callback_data(subreq,
struct tevent_req);
bool ok;
ok = tevent_wakeup_recv(subreq);
TALLOC_FREE(subreq);
if (!ok) {
tevent_req_error(req, -1);
return;
}
...
}
subreq = tevent_wakeup_send(mem_ctx, ev, wakeup_time);
if (tevent_req_nomem(subreq, req)) {
return false;
}
tevent_set_callback(subreq, my_callback_wakeup_done, req);
Like β see how my_callback_wakeup_done() grabs the parent req back out with tevent_req_callback_data(), calls tevent_wakeup_recv() to collect the result, then TALLOC_FREE()s the subrequest before checking ok? That's the whole pattern. And on the sending side, tevent_req_nomem() is your bestie for bailing early if the subrequest couldn't even be created, and tevent_set_callback() is how the callback gets wired up. No notes. β¨
See also π«Ά
tevent_wakeup_recv()β literally the other half of this duo, the recv side of the wakeup.
Author π
Generated automatically by Doxygen for tevent from the source code.
And that's a wrap, bestie!! πΈ This iconic little page comes straight outta tevent Version 0.9.8, and in the man pages it's filed under tevent_request(3). Go forth and request responsibly, mwah ππ¦β¨
π¦ where this page comes from
- centos-stream 10: libtevent-devel 0.17.1-100.el10 Β· LGPL-3.0-or-later
- fedora 43: libtevent-devel 0.17.1-3.fc43 Β· LGPL-3.0-or-later
- fedora 43: libtevent-devel 0.17.1-3.fc43 Β· LGPL-3.0-or-later
- opensuse-leap 16.0: tevent-man 0.16.2-160000.2.2 Β· LGPL-3.0-or-later
- opensuse-leap 16.0: tevent-man 0.16.2-160000.2.2 Β· LGPL-3.0-or-later
- opensuse-leap 16.0: tevent-man 0.16.2-160000.2.2 Β· LGPL-3.0-or-later
- opensuse-leap 16.0: tevent-man 0.16.2-160000.2.2 Β· LGPL-3.0-or-later
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms