SSL_POLL(3ossl)
π
SSL_POLL(3ossl) β the 3ossl manual page, but make it make sense
okay bestie, pull up a chair because we're about to talk about the single most β¨group-chatβ¨-worthy thing in OpenSSL: polling a whole bunch of pollable objects at once. yes, this is part one of two, so hydrate and stay with me.
πΈ NAME πΈ
SSL_poll, SSL_POLL_EVENT_NONE, SSL_POLL_EVENT_F, SSL_POLL_EVENT_EL, SSL_POLL_EVENT_EC, SSL_POLL_EVENT_ECD, SSL_POLL_EVENT_ER, SSL_POLL_EVENT_EW, SSL_POLL_EVENT_R, SSL_POLL_EVENT_W, SSL_POLL_EVENT_IC, SSL_POLL_EVENT_ISB, SSL_POLL_EVENT_ISU, SSL_POLL_EVENT_OSB, SSL_POLL_EVENT_OSU, SSL_POLL_EVENT_RW, SSL_POLL_EVENT_RE, SSL_POLL_EVENT_WE, SSL_POLL_EVENT_RWE, SSL_POLL_EVENT_E, SSL_POLL_EVENT_IS, SSL_POLL_EVENT_ISE, SSL_POLL_EVENT_I, SSL_POLL_EVENT_OS, SSL_POLL_EVENT_OSE, SSL_POLL_FLAG_NO_HANDLE_EVENTS β determine or await readiness conditions for one or more pollable objects π
like⦠it's giving "wait, is anything ready yet?" but for a whole little friend group of resources at the same time. iconic behavior honestly.
β¨ SYNOPSIS β¨
#include <openssl/ssl.h>
#define SSL_POLL_EVENT_NONE 0
#define SSL_POLL_EVENT_F /* F (Failure) */
#define SSL_POLL_EVENT_EL /* EL (Exception on Listener) */
#define SSL_POLL_EVENT_EC /* EC (Exception on Conn) */
#define SSL_POLL_EVENT_ECD /* ECD (Exception on Conn Drained) */
#define SSL_POLL_EVENT_ER /* ER (Exception on Read) */
#define SSL_POLL_EVENT_EW /* EW (Exception on Write) */
#define SSL_POLL_EVENT_R /* R (Readable) */
#define SSL_POLL_EVENT_W /* W (Writable) */
#define SSL_POLL_EVENT_IC /* IC (Incoming Connection) */
#define SSL_POLL_EVENT_ISB /* ISB (Incoming Stream: Bidi) */
#define SSL_POLL_EVENT_ISU /* ISU (Incoming Stream: Uni) */
#define SSL_POLL_EVENT_OSB /* OSB (Outgoing Stream: Bidi) */
#define SSL_POLL_EVENT_OSU /* OSU (Outgoing Stream: Uni) */
#define SSL_POLL_EVENT_RW /* R | W */
#define SSL_POLL_EVENT_RE /* R | ER */
#define SSL_POLL_EVENT_WE /* W | EW */
#define SSL_POLL_EVENT_RWE /* RE | WE */
#define SSL_POLL_EVENT_E /* EL | EC | ER | EW */
#define SSL_POLL_EVENT_IS /* ISB | ISU */
#define SSL_POLL_EVENT_ISE /* IS | EC */
#define SSL_POLL_EVENT_I /* IS */
#define SSL_POLL_EVENT_OS /* OSB | OSU */
#define SSL_POLL_EVENT_OSE /* OS | EC */
typedef struct ssl_poll_item_st {
BIO_POLL_DESCRIPTOR desc;
uint64_t events, revents;
} SSL_POLL_ITEM;
#define SSL_POLL_FLAG_NO_HANDLE_EVENTS
int SSL_poll(SSL_POLL_ITEM *items,
size_t num_items,
size_t stride,
const struct timeval *timeout,
uint64_t flags,
size_t *result_count);
look at that struct. desc, events, revents. three little fields carrying the whole vibe check π«Ά
π¦ DESCRIPTION π¦
SSL_poll() is literally here so you can figure out the readiness conditions of the resources represented by one or more BIO_POLL_DESCRIPTOR structures. and not just one at a time, bestie β it can query readiness on QUIC connection SSL objects and QUIC stream SSL objects in a single call. one call. one. periodt. it can also block until at least one of those resources is ready, if that's the energy you're bringing.
so when you call SSL_poll(), you're handing it an array of SSL_POLL_ITEM structures. each one points at a resource you're polling for readiness, plus a set of event flags saying exactly which readiness events you care about for that resource. like a little RSVP list for your events π
π the fields of SSL_POLL_ITEM
descβ the resource being polled for readiness, represented as aBIO_POLL_DESCRIPTOR. rn it must be a poll descriptor of typeBIO_POLL_DESCRIPTOR_TYPE_SSL, which means it represents an SSL object pointer β and that SSL object has to be a QUIC connection SSL object or a QUIC stream SSL object. no other options, no cap.
also important: if anSSL_POLL_ITEMhas a poll descriptor type ofBIO_POLL_DESCRIPTOR_TYPE_NONE, or the SSL object pointer isNULL, that array entry gets ignored, andreventsgets set to0when the call returns. it's a ghost π»
eventsβ the set of zero or more events you're interested in learning about for the resource indesc. it's a collection of zero or moreSSL_POLL_EVENTflags. head down to EVENT TYPES for what each one means.reventsβ afterSSL_poll()returns, this is the set of zero or more events that actually apply to the resource indesc. same deal asevents: a collection of zero or moreSSL_POLL_EVENTflags.
heads up bestie:reventsdoes not have to be a subset of what you put inevents, because some event types are defined as always being enabled (non-maskable). again, see EVENT TYPES.
π how to actually use it
to use SSL_poll(), call it with an array of SSL_POLL_ITEM structures. the array only needs to stay allocated for the duration of the call β you can let it go after, she's free π
num_items must be set to the number of entries in the array. stride must be set to sizeof(SSL_POLL_ITEM). that's the whole assignment, no surprises.
β° the timeout argument
the timeout argument says how long to wait and, implicitly, whether SSL_poll() is running in blocking or nonblocking mode. here's the breakdown:
- if
timeoutisNULL, the function blocks indefinitely until at least one resource is ready. like, forever-forever. it will wait. π - if
timeoutis non-NULLand it points to astruct timevalset to zero, the function operates in nonblocking mode and returns immediately with readiness info. in and out, no loitering β¨ - if
timeoutis non-NULLand it points to astruct timevalset to a value other than zero, the function blocks for that specified interval, or until at least one of the specified resources is ready β whichever comes first. a lil race, cute π
the present implementation of SSL_poll() is a subset of the functionality that will eventually be available. for more info, go read LIMITATIONS. we're in the build-a-bear era of this API, okay?
π the flags argument π
the following flags are currently defined for the flags argument:
SSL_POLL_FLAG_NO_HANDLE_EVENTSβ this flag says internal state machine processing should not be performed in an attempt to generate new readiness events. only existing readiness events get reported. no new ones, just the ones already in the building π- if this flag is used in nonblocking mode (with a timeout of zero), no internal state machine processing is performed.
- if this flag is used in blocking mode (for example, with
timeoutset toNULL), event processing does not occur unless the function blocks.
π the result_count argument
result_count is optional. if it's non-NULL, it's used to output the number of entries in the array that have nonzero revents fields when the call to SSL_poll() returns. details live in RETURN VALUES, so go check that out next. π«Ά
more to come, bestie β this page keeps going and so do we π§
π EVENT TYPES π
Okay so SSL_poll() reports zero or more event types on a given resource, and it does it with a bit mask. Cute, right? β¨
Here's the tea on how they behave: all of the event types are level triggered and they represent a readiness or permanent exception condition. Which means β and this is the important part bestie β once SSL_poll() has reported an event for a resource, it's gonna keep reporting it in future SSL_poll() calls until that condition stops being in effect. π So if you don't want the same notification on loop, you gotta mask that event type bit out in your future SSL_poll() calls β unless you've already made the underlying readiness condition go away (like, say, consuming all the available data with SSL_read_ex(3) after SSL_POLL_EVENT_R gets reported). Then it's deasserted and you're free π
Some event types just don't make sense on a given kind of resource. If that's the case, putting that event type in events is a total no-op, it gets ignored, and that event will never show up in revents. Periodt. π
Failure of the polling mechanism itself is a completely different thing from an exception condition on a resource that got successfully polled. See SSL_POLL_EVENT_F and "RETURN VALUES" for the details on that one. π₯
Also, general life advice: an application should always listen for the event types that correspond to exception conditions if it's listening to the corresponding non-exception event types (e.g. SSL_POLL_EVENT_EC and SSL_POLL_EVENT_ER for SSL_POLL_EVENT_R). Not doing that is, and I quote, "unlikely to be a sound design." π
And some event types are non-maskable β they may get reported in revents whether or not you asked for them in events. Sneaky. π
Here's the full roster of supported event types:
SSL_POLL_EVENT_F
Polling failure, bestie. π This one is raised when a resource could not be polled. It is distinct from an exception condition reported on a resource that was successfully polled β this is a failure of the polling process itself in relation to a resource. It may mean that SSL_poll() doesn't support the kind of resource you specified. π
Where this event is raised on at least one item in items, SSL_poll() will return 0 and the ERR stack will contain info pertaining to the first item in items with SSL_POLL_EVENT_F set. See "RETURN VALUES" for more. π«Ά
This event type may be raised even if it was not requested in events; specifying this event type in events does nothing.
SSL_POLL_EVENT_EL
Error at listener level. π Raised when a listener has failed β for example if a network BIO has encountered a permanent error.
This event is never raised on objects which are not listeners, but its occurrence will cause SSL_POLL_EVENT_EC to be raised on all dependent connections. Ripple effect, iconic. π
SSL_POLL_EVENT_EC
Error at connection level. Raised when a connection has failed. In particular, it's raised when a connection begins terminating. π
This event is never raised on objects which are not connections.
SSL_POLL_EVENT_ECD
Error at connection level, but drained. β¨ Raised when a connection has finished terminating and has reached the terminated state. This one will generally show up after an interval of time passes after the SSL_POLL_EVENT_EC event is raised on a connection.
This event is never raised on objects which are not connections.
SSL_POLL_EVENT_ER
Error in the read direction. π For QUIC, this is raised only in the event that a stream has a read part and that read part has been reset by the peer (for example, using a RESET_STREAM frame).
SSL_POLL_EVENT_EW
Error in the write direction. βοΈ For QUIC, this is raised only in the event that a stream has a write part and that write part has been reset by the peer using a STOP_SENDING frame.
SSL_POLL_EVENT_R
Readable. πΈ Raised when a QUIC stream SSL object (or a QUIC connection SSL object with a default stream attached) has application data waiting to be read using SSL_read_ex(3), or a FIN event as represented by SSL_ERROR_ZERO_RETURN waiting to be read.
It is not raised in the event of the receiving part of the QUIC stream being reset by the peer β see SSL_POLL_EVENT_ER for that.
SSL_POLL_EVENT_W
Writable. ποΈ Raised when a QUIC stream SSL object (or a QUIC connection SSL object with a default stream attached) could accept more application data using SSL_write_ex(3).
This event is never raised by a receive-only stream.
This event is never raised by a stream which has had its send part concluded normally (as with SSL_stream_conclude(3)) or locally reset (as with SSL_stream_reset(3)).
Heads up: this event does not guarantee that a subsequent call to SSL_write_ex(3) will succeed. π
SSL_POLL_EVENT_IC
This one is raised only by a QUIC listener SSL object π, and it fires when one or more incoming QUIC connections are available to be accepted using SSL_accept_connection(3).
SSL_POLL_EVENT_ISB
Raised only by a QUIC connection SSL object, when one or more incoming bidirectional streams are available to be accepted using SSL_accept_stream(3). π¦
SSL_POLL_EVENT_ISU
Raised only by a QUIC connection SSL object, when one or more incoming unidirectional streams are available to be accepted using SSL_accept_stream(3). π¦
SSL_POLL_EVENT_OSB
Raised only by a QUIC connection SSL object, when QUIC stream creation flow control currently permits at least one additional bidirectional stream to be locally created. β¨
SSL_POLL_EVENT_OSU
Raised only by a QUIC connection SSL object, when QUIC stream creation flow control currently permits at least one additional unidirectional stream to be locally created. β¨
π§ LIMITATIONS π§
SSL_poll() as presently implemented has the following limitation, and I need you to sit with this one:
- Only
BIO_POLL_DESCRIPTORstructures with typeBIO_POLL_DESCRIPTOR_TYPE_SSL, referencing QUIC listener, connection or stream SSL objects, are supported. π
This limitation may be revised in a future release of OpenSSL. So likeβ¦ stay tuned bestie. π
π THREAD CANCELLATION π
A finite timeout limits ordinary waiting by SSL_poll(), but it does not make the call safe against thread cancellation β go read openssl-threads(7). π¬
Cancellation can prevent SSL_poll() from removing internal wait state. And because an items array can span multiple QUIC domains, one interrupted call can leave stale state in several domains and cause later calls on those domains β including SSL_poll() with a finite timeout β to block indefinitely. Not cute at all. π
For cooperative cancellation, use a finite timeout and check a cancellation condition between calls; see "THREAD CANCELLATION" in openssl-quic-concurrency(7) for the nonblocking alternative. π«Ά
π¬ RETURN VALUES π¬
SSL_poll() returns 1 on success and 0 on failure. Simple. π
Unless the items pointer itself is invalid, SSL_poll() will always initialise the revents fields of all items in the input array upon returning β even if it returns failure. β¨
If result_count is non-NULL, it is always written with the number of items in the array with nonzero revents fields, even if the SSL_poll() call returns failure. π
It is possible for result_count to be written as 0 even if the SSL_poll() call returns success β namely if no events were output but the polling process was successful (e.g. in nonblocking usage) or timed out. π€·
It is also possible for result_count to be written as a nonzero value if the SSL_poll() call returns failure β for example due to SSL_POLL_EVENT_F events, or because some events were detected and output before encountering a failure condition while processing a subsequent entry in the items array. π
If at least one SSL_POLL_EVENT_F event is output, SSL_poll() is guaranteed to return 0 and guaranteed to place at least one ERR on the error stack describing the first SSL_POLL_EVENT_F output. Detailed information on any additional SSL_POLL_EVENT_F events is not available. SSL_poll() may or may not return more than one SSL_POLL_EVENT_F event at once. π
"Normal" events representing exceptional I/O conditions which do not constitute a failure of the SSL_poll() mechanism itself are not considered errors by SSL_poll() β they get represented using their own event type instead. See "EVENT TYPES" for the details. π
So here's how you, the caller, can decode the return value and output values, step by step:
- If
SSL_poll()returns1andresult_countis zero β the operation timed out before any resource was ready. π - If
SSL_poll()returns1andresult_countis nonzero β that many events were output. π - If
SSL_poll()returns0andresult_countis zero β you, the caller, have made a basic usage error. Go check theERRstack for details. π - If
SSL_poll()returns0andresult_countis nonzero β inspect theitemsarray forSSL_POLL_ITEMstructures with theSSL_POLL_EVENT_Fevent type raised inrevents. The entries added to theERRstack (of which there is guaranteed to be at least one) reflect the cause of the failure of the first item initemswithSSL_POLL_EVENT_Fraised. Note that there may be events other thanSSL_POLL_EVENT_Foutput for items which come before the first item withSSL_POLL_EVENT_Fraised, and additionalSSL_POLL_EVENT_Fevents may or may not have been output β both of which will be reflected inresult_count. π«Ά
π SEE ALSO π
BIO_get_rpoll_descriptor(3)BIO_get_wpoll_descriptor(3)SSL_get_rpoll_descriptor(3)SSL_get_wpoll_descriptor(3)openssl-threads(7)openssl-quic(7)openssl-quic-concurrency(7)
π HISTORY π
SSL_poll() was added in OpenSSL 3.3. π±
Before 3.5, SSL_poll() did not support blocking operation and would fail if called with a NULL timeout parameter or a timeout parameter pointing to a struct timeval which was not zero. π¬
Before 3.5, the SSL_POLL_EVENT_EL and SSL_POLL_EVENT_IC event types were not present. π¦
π COPYRIGHT π
Copyright 2024-2026 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy in the file LICENSE in the source distribution or at https://www.openssl.org/source/license.html.
And that's a wrap on SSL_POLL(3ossl) from OpenSSL 3.5.9, dated 2026-09-29 π go poll something, bestie, and mask your bits π
β¨π¦
π¦ where this page comes from
- fedora 43: openssl-devel 1:3.5.9-1.fc43 Β· Apache-2.0
- fedora 43: openssl-devel 1:3.5.9-1.fc43 Β· Apache-2.0
- fedora 44: openssl-devel 1:3.5.9-1.fc44 Β· Apache-2.0
- fedora 44: openssl-devel 1:3.5.9-1.fc44 Β· Apache-2.0
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms