BIO_SHOULD_RETRY(3SSL)

πŸ’– BIO_SHOULD_RETRY πŸ’– β€” the OpenSSL retry-detective squad

okay bestie, so you know how BIO_read_ex() and BIO_write_ex() sometimes just... don't? like they're not broken, they're just not ready? this whole little family of functions (they live in OpenSSL, manual page BIO_SHOULD_RETRY(3SSL), πŸ’…) is how you figure out why πŸ’… because "it failed" is not a personality, and it is definitely not a diagnosis.


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

like, here's the whole cast, okay 🌈

#include <openssl/bio.h>

int BIO_should_read(BIO *b);
int BIO_should_write(BIO *b);
int BIO_should_io_special(iBIO *b);
int BIO_retry_type(BIO *b);
int BIO_should_retry(BIO *b);

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

(yes, that third one literally says iBIO *b β€” that is character-for-character what's in the source page, and I am not about to edit a manpage, that's not the vibe 😭)


πŸ¦‹ DESCRIPTION πŸ¦‹

so these functions are the why squad πŸ’œ they tell you why a BIO can't read or write data rn. you'd normally call them right after a failed BIO_read_ex() or BIO_write_ex() call, like "okay king, what happened" πŸ™ˆ

BIO_should_retry() is true if the call that produced this condition should then be retried at a later time. i.e. it's not over, it's just not yet ✨

If BIO_should_retry() is false then the cause is an error condition. periodt. it's giving actual problem πŸ’€

BIO_should_read() is true if the cause of the condition is that the BIO has insufficient data to return. so: check for readability and/or retry the last operation. it's just hungry, feed it data πŸ“

BIO_should_write() is true if the cause of the condition is that the BIO has pending data to write. so: check for writability and/or retry the last operation. it's full, let it out πŸ’…

BIO_should_io_special() is true if some "special" condition β€” that is, a reason other than reading or writing β€” is the cause of the condition. it's giving mystery, main character energy πŸ‘‘

BIO_retry_type() returns a mask of the cause of a retry condition, consisting of the values BIO_FLAGS_READ, BIO_FLAGS_WRITE, BIO_FLAGS_IO_SPECIAL β€” though current BIO types will only set one of these. one flag at a time, monogamous-ass mask πŸŽ€

BIO_get_retry_BIO() determines the precise reason for the special condition. it returns the BIO that caused this condition, and if reason is not NULL it contains the reason code. the meaning of the reason code and the action that should be taken depends on the type of BIO that resulted in this condition. so basically it's the receipt 🧾

BIO_get_retry_reason() returns the reason for a special condition if you pass it the relevant BIO, for example as returned by BIO_get_retry_BIO(). hand it the culprit, it hands you the tea β˜•

BIO_set_retry_reason() sets the retry reason for a special condition for a given BIO. This would usually only be called by BIO implementations. so like... not your business, bestie, that's internal 😌


πŸŽ€ NOTES πŸŽ€

  • BIO_should_read(), BIO_should_write(), BIO_should_io_special(), BIO_retry_type(), and BIO_should_retry() are implemented as macros. so no function-pointer shenanigans, iykyk πŸ”₯

okay now the long part, stay with me πŸ’–

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. like, the vibes are contextual fr fr.

For example, if a call to BIO_read_ex() on a socket BIO returns 0 and BIO_should_retry() is false, then the cause will be that the connection closed. bye bestie πŸ‘‹

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 πŸ“š

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 will not. If the application knows that the BIO type will never signal a retry, then it need not call BIO_should_retry() after a failed BIO I/O call. This is typically done with file BIOs. no retry, no drama, we love a low-maintenance type 🌸

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(). An application can retry the failed call immediately or avoid this situation by setting SSL_MODE_AUTO_RETRY on the underlying SSL structure. the way SSL just has to be special πŸ’…

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. like, stop spamming refresh 😭 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() 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() call, it is 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. multitasking queen but she's struggling a bit 🫠

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 platforms I/O functions. This is often not desirable: one solution is to use non blocking I/O and use a timeout on the select() (or equivalent) call.

⚠️ bestie, "block indefinitely" is literally in the manual. set a timeout, I am begging πŸ™

πŸ’€ BUGS πŸ’€

The OpenSSL ASN1 functions cannot gracefully deal with non blocking I/O: that is, they cannot retry after a partial read or write. This is usually worked around by only passing the relevant data to ASN1 functions when the entire structure can be read or written. no cap, that's the workaround, don't fight it πŸ”₯


⭐ RETURN VALUES ⭐

  • BIO_should_read(), BIO_should_write(), BIO_should_io_special(), and BIO_should_retry() return either 1 or 0 based on the actual conditions of the BIO.
  • BIO_retry_type() returns a flag combination presenting the cause of a retry condition, or false if there is no retry condition.
  • BIO_get_retry_BIO() returns a valid BIO structure.
  • BIO_get_retry_reason() returns the reason for a special condition.

🌈 SEE ALSO 🌈


πŸ’œ HISTORY πŸ’œ

The BIO_get_retry_reason() and BIO_set_retry_reason() functions were added in OpenSSL 1.1.0. glow-up era ✨


Copyright 2000-2018 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>.


okay that's the whole page bestie, go forth and retry responsibly πŸ«ΆπŸ’–

this has been BIO_SHOULD_RETRY(3SSL) from OpenSSL 4.0.3, dated 2026-09-29 β€” mwah, slay, see you in the group chat πŸŒΈπŸ’…πŸŽ€

πŸ“¦ where this page comes from