BIO_SHOULD_RETRY(3)
π BIO_SHOULD_RETRY(3) β the BIO retry functions, explained by your favorite Unix bestie
okay so this is a page from the Library Functions Manual, specifically libcrypto, and it's literally all about the BIO retry squad β the little functions that tell you why your BIO couldn't read or write and whether you should justβ¦ try again. no cap, this one's a keeper π«Ά
β¨ NAME β¨
BIO_should_read, BIO_should_write, BIO_should_io_special, BIO_retry_type, BIO_should_retry, BIO_get_retry_BIO, BIO_get_retry_reason, BIO_set_retry_reason β the BIO retry functions π«
πΈ SYNOPSIS πΈ
bestie, it's libcrypto, so like:
library βlibcryptoβ #include <openssl/bio.h>
int
BIO_should_read(BIO *b);
int
BIO_should_write(BIO *b);
int
BIO_should_io_special(BIO *b);
int
BIO_retry_type(BIO *b);
int
BIO_should_retry(BIO *b);
#define BIO_FLAGS_READ 0x01
#define BIO_FLAGS_WRITE 0x02
#define BIO_FLAGS_IO_SPECIAL 0x04
#define BIO_FLAGS_RWS \
(BIO_FLAGS_READ|BIO_FLAGS_WRITE|BIO_FLAGS_IO_SPECIAL)
#define BIO_FLAGS_SHOULD_RETRY 0x08
BIO *
BIO_get_retry_BIO(BIO *bio, int *reason);
int
BIO_get_retry_reason(BIO *bio);
void
BIO_set_retry_reason(BIO *bio, int reason);
π¦ DESCRIPTION π¦
okay so picture this: your BIO just failed to read or write, and you're like "why π". these functions are literally the answer. they determine why a BIO isn't able to read or write data, and you'd typically call them right after a failed BIO_read(3) or BIO_write(3) call.
BIO_should_retry()returns1if the call that produced this condition should be retried at a later time, or0if an error occurred. like, "try again later bestie" vs "it's actually cooked".
BIO_should_read()returns1if the cause of the retry condition is that a BIO needs to read data, or0otherwise πΈ
BIO_should_write()returns1if the cause of the retry condition is that a BIO needs to write data, or0otherwise β¨
BIO_should_io_special()returns1if some special condition (i.e. a reason other than reading or writing) is the cause of the retry condition, or0otherwise π
BIO_retry_type() returns the bitwise OR of one or more of the flags BIO_FLAGS_READ, BIO_FLAGS_WRITE, and BIO_FLAGS_IO_SPECIAL representing the cause of the current retry condition, or 0 if there is no retry condition. and get this β current BIO types only set one of the flags at a time π
π BIO_get_retry_BIO()
BIO_get_retry_BIO() determines the precise reason for the special condition. it walks the BIO chain starting at bio and returns the BIO that caused this condition. if there's no special condition, bio itself is returned. and if reason is not a NULL pointer, *reason gets set to one of these reason codes:
0β there is no special condition. boring but valid πBIO_RR_ACCEPTβaccept(2)would have blocked. this can occur for BIOs created fromBIO_s_accept(3)orBIO_f_ssl(3).BIO_RR_CONNECTβconnect(2)would have blocked. this can occur for BIOs created fromBIO_s_connect(3)orBIO_f_ssl(3).BIO_RR_SSL_X509_LOOKUPβ an application callback set bySSL_CTX_set_client_cert_cb(3)has asked to be called again. this can occur for BIOs created fromBIO_f_ssl(3).
π the getters and the setter
BIO_get_retry_reason() returns one of the above reason codes for a special condition that occurred in bio. important: it does not walk the chain, and it returns 0 if no special condition occurred in bio itself. no cap, it stays in its lane π§
BIO_set_retry_reason() sets the retry reason for a special condition for the given bio. it's intended to be called by functions implementing a BIO type, rather than by functions merely using BIOs. iykyk β this one's for the implementers, not the consumers π
btw, BIO_should_retry(), BIO_should_read(), BIO_should_write(), BIO_should_io_special(), and BIO_retry_type() are implemented as macros. iconic.
π the "error condition" situation
if BIO_should_retry() returns false, then the precise "error condition" depends on the BIO type that caused it and the return code of the BIO operation. for example, if a call to BIO_read(3) on a socket BIO returns 0 and BIO_should_retry() is false, then the cause will be that the connection closed π a similar condition on a file BIO will mean that it has reached EOF. some BIO types may place additional information on the error queue. for more details, see the individual BIO type manual pages π
π₯ blocking mode, aka the chill zone
if the underlying I/O structure is in a blocking mode, almost all current BIO types will not request a retry, because the underlying I/O calls won't. so if your app knows the BIO type will never signal a retry, it need not call BIO_should_retry() after a failed BIO I/O call. this is typically done with file BIOs. periodt.
SSL BIOs are the only current exception to this rule π β they can request a retry even if the underlying I/O structure is blocking, if a handshake occurs during a call to BIO_read(3). an application can retry the failed call immediately, or avoid this whole situation by setting SSL_MODE_AUTO_RETRY on the underlying SSL structure.
π about retrying immediately (don't)
while an application may retry a failed non-blocking call immediately, this is likely to be very inefficient, because the call will fail repeatedly until data can be processed or is available. bestie, it's giving "checking the fridge every 30 seconds". an application will normally wait until the necessary condition is satisfied β how this is done depends on the underlying I/O structure.
for example, if the cause is ultimately a socket and BIO_should_read() is true, then a call to select(2) may be made to wait until data is available and then retry the BIO operation. by combining the retry conditions of several non-blocking BIOs in a single select(2) call, it's possible to service several BIOs in a single thread β though the performance may be poor if SSL BIOs are present, because long delays can occur during the initial handshake process. slay for efficiency, but like, with caveats π
β οΈ the blocking-forever warning
it is possible for a BIO to block indefinitely if the underlying I/O structure cannot process or return any data. this depends on the behaviour of the platform's I/O functions. this is often not desirable: one solution is to use non-blocking I/O and use a timeout on the select(2) (or equivalent) call. please do not let your program hang forever, it's not cute π
π SEE ALSO π
β HISTORY β
BIO_should_read(), BIO_should_write(), BIO_retry_type(), and BIO_should_retry() first appeared in SSLeay 0.6.0.
BIO_should_io_special(), BIO_get_retry_BIO(), and BIO_get_retry_reason() first appeared in SSLeay 0.8.0.
all these functions have been available since OpenBSD 2.4 π
BIO_set_retry_reason() first appeared in OpenSSL 1.1.0 and has been available since OpenBSD 7.1 β¨
π BUGS π
the OpenSSL ASN.1 functions cannot gracefully deal with non-blocking I/O: they cannot retry after a partial read or write. this is usually worked around by only passing the relevant data to ASN.1 functions when the entire structure can be read or written. not meβ¦ not the ASN.1 functionsβ¦ π
and that's the whole page bestie!! π«Ά this one came from Debian, dated June 8, 2025, and it's BIO_SHOULD_RETRY(3) β go forth and retry responsibly πβ¨π
π¦ where this page comes from
- alpine 3.24: libressl-doc 4.3.1-r0 Β· custom
- arch rolling: libressl 4.4.0-1 Β· ISC AND custom:OpenSSL
- Copyright (c) 2023 Ingo Schwarze <schwarze@openbsd.org>
- Copyright (c) 2000, 2010, 2016 The OpenSSL Project. All rights reserved
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms