[nginx] SSL: optimized SSL_sendfile() usage on FreeBSD.

Maxim Dounin mdounin at mdounin.ru
Fri Jan 30 10:43:40 UTC 2026


details:   http://freenginx.org/hg/nginx/rev/2d9f74de4dc2
branches:  
changeset: 9460:2d9f74de4dc2
user:      Maxim Dounin <mdounin at mdounin.ru>
date:      Fri Jan 30 13:27:45 2026 +0300
description:
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.

diffstat:

 src/event/ngx_event_openssl.c |  16 +++++++++++++++-
 1 files changed, 15 insertions(+), 1 deletions(-)

diffs (40 lines):

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 == NGX_EAGAIN) {
+            c->write->ready = 0;
+        }
+
         return n;
     }
 


More information about the nginx-devel mailing list