This is an automated email from the ASF dual-hosted git repository.

ChristopherSchultz pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tomcat-connectors.git

commit ed383e12ca21035f42c4bcb8cb128f8ee63363ae
Author: Christopher Schultz <[email protected]>
AuthorDate: Mon Jun 8 18:18:32 2026 -0400

    Fix a few issues in jk_sb_send
    
    Tolerate situations where send() does not send the complete message on the 
first try
    Writing a zero-length buffer is always successful
---
 native/common/jk_sockbuf.c | 78 ++++++++++++++++++++++++++++++++++++----------
 1 file changed, 61 insertions(+), 17 deletions(-)

diff --git a/native/common/jk_sockbuf.c b/native/common/jk_sockbuf.c
index 32c53931a..b82d78fdb 100644
--- a/native/common/jk_sockbuf.c
+++ b/native/common/jk_sockbuf.c
@@ -37,33 +37,77 @@ int jk_sb_open(jk_sockbuf_t *sb, jk_sock_t sd)
     return JK_FALSE;
 }
 
-int jk_sb_write(jk_sockbuf_t *sb, const void *buf, unsigned sz)
+/* send all data in buf (up to len) to the file descriptor */
+static int jk_sb_send_all(int sd, const void *buf, size_t len)
 {
-    if (sb && buf && sz) {
-        if (sb->end >= SOCKBUF_SIZE) {
-            return JK_FALSE;
-        }
+    size_t total = 0;
+
+    if (len == 0) {
+        return JK_TRUE;
+    }
 
-        if (sz <= SOCKBUF_SIZE - sb->end) {
-            memcpy(sb->buf + sb->end, buf, sz);
-            sb->end += sz;
+    while (total < len) {
+        ssize_t n = send(sd,
+                         (const char *)buf + total,
+                         len - total,
+                         0);
+
+        if (n > 0) {
+            total += (size_t)n;
+            continue;
         }
-        else {
-            if (!jk_sb_flush(sb)) {
-                return JK_FALSE;
-            }
-            if (sz > SOCKBUF_SIZE) {
-                return (send(sb->sd, (char *)buf, sz, 0) == (int)sz);
+
+        if (n == -1) {
+            if (errno == EINTR) {
+                continue; // interrupted, retry
             }
 
-            memcpy(sb->buf + sb->end, buf, sz);
-            sb->end += sz;
+            // Any other error is fatal for this write
+            return JK_FALSE;
         }
 
+        // n == 0: treat as connection closed or invalid state
+        return JK_FALSE;
+    }
+
+    return JK_TRUE;
+}
+
+int jk_sb_write(jk_sockbuf_t *sb, const void *buf, unsigned sz)
+{
+    if (!sb || !buf) {
+        return JK_FALSE;
+    }
+    if (sz == 0) {
         return JK_TRUE;
     }
 
-    return JK_FALSE;
+    if (sb->end >= SOCKBUF_SIZE) {
+        return JK_FALSE;
+    }
+
+    if (sz <= SOCKBUF_SIZE - sb->end) {
+        memcpy(sb->buf + sb->end, buf, sz);
+        sb->end += sz;
+
+        return JK_TRUE;
+    }
+
+    /* write cannot fit into remaining buffer, so flush */
+    if (!jk_sb_flush(sb)) {
+        return JK_FALSE;
+    }
+
+    /* don't buffer writes that will never fit */
+    if (sz > SOCKBUF_SIZE) {
+        return jk_sb_send_all(sb->sd, buf, sz);
+    }
+
+    /* buffer small write-after-flush */
+    memcpy(sb->buf + sb->end, buf, sz);
+    sb->end += sz;
+
+    return JK_TRUE;
 }
 
 int jk_sb_flush(jk_sockbuf_t *sb)


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to