[PATCH] SSL: optimized SSL_sendfile() usage on FreeBSD

Maxim Dounin mdounin at mdounin.ru
Thu Jan 29 00:25:46 UTC 2026


Hello!

On Wed, Jan 28, 2026 at 03:52:27AM +0300, Maxim Dounin wrote:

> # HG changeset patch
> # User Maxim Dounin <mdounin at mdounin.ru>
> # Date 1769472200 -10800
> #      Tue Jan 27 03:03:20 2026 +0300
> # Node ID c3f9073f36cc89ee57cc1e09d2de1449060e3687
> # Parent  80f7b4a9363e71819963ecc3283c4f41caf12cfc
> SSL: optimized SSL_sendfile() usage on FreeBSD.
> 
> On FreeBSD sendfile() syscall returns an error with errno set to EAGAIN
> when the socket buffer is full (along with the number of bytes sent).
> Unfortunately, the SSL_sendfile() interface loses this information, and
> an extra SSL_sendfile() call is needed to obtain EAGAIN, typically
> resulting in doubled sendfile() syscalls.
> 
> With this change, if errno is set to EAGAIN after the SSL_sendfile()
> call, we assume it was set by sendfile() and the socket buffer is full.
> This is generally safe as we clear errno before the SSL_sendfile() call,
> and saves an extra sendfile() syscall.
> 
> Prodded by Gleb Smirnoff.
> 
> diff --git a/src/event/ngx_event_openssl.c b/src/event/ngx_event_openssl.c
> --- a/src/event/ngx_event_openssl.c
> +++ b/src/event/ngx_event_openssl.c
> @@ -3277,6 +3277,10 @@ ngx_ssl_send_chain(ngx_connection_t *c, 
>                  send += n;
>                  flush = 0;
>  
> +                if (!c->write->ready) {
> +                    break;
> +                }
> +
>                  continue;
>              }
>  
> @@ -3595,7 +3599,7 @@ ngx_ssl_sendfile(ngx_connection_t *c, ng
>  
>      err = ngx_socket_errno;
>  
> -    ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_sendfile: %z", n);
> +    ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, err, "SSL_sendfile: %z", n);
>  
>      if (n > 0) {
>  
> @@ -3618,6 +3622,16 @@ ngx_ssl_sendfile(ngx_connection_t *c, ng
>  
>          c->sent += n;
>  
> +        /*
> +         * on FreeBSD sendfile(), along with the number of bytes sent,
> +         * returns an error with errno set to EAGAIN when the socket buffer
> +         * is full
> +         */
> +
> +        if (err == EAGAIN) {

Should be:

-        if (err == EAGAIN) {
+        if (err == NGX_EAGAIN) {

No real difference here, but in general NGX_E... error codes 
should be used to ensure portability.

Fixed in the patch.

> +            c->write->ready = 0;
> +        }
> +
>          return n;
>      }
>  
> 

-- 
Maxim Dounin
http://mdounin.ru/


More information about the nginx-devel mailing list