Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 17 additions & 6 deletions src/nxt_conn_write.c
Original file line number Diff line number Diff line change
Expand Up @@ -118,12 +118,8 @@ nxt_conn_io_write(nxt_task_t *task, void *obj, void *data)
}
}

if (ret == 0 || sb.sent != 0) {
/*
* ret == 0 means a sync buffer was processed.
* ret == NXT_ERROR is ignored here if some data was sent,
* the error will be handled on the next nxt_conn_write() call.
*/
if (ret == 0 || (ret != NXT_ERROR && sb.sent != 0)) {
/* ret == 0 means a sync buffer was processed. */
c->sent += sb.sent;
nxt_work_queue_add(c->write_work_queue, c->write_state->ready_handler,
task, c, data);
Expand All @@ -134,6 +130,21 @@ nxt_conn_io_write(nxt_task_t *task, void *obj, void *data)
return;
}

if (sb.sent != 0) {
/*
* Pattern D′: route to error_handler immediately when a write
* returns NXT_ERROR after a partial send (e.g. peer closed
* mid-response). Pre-fix, this case fell through to
* ready_handler and the error was deferred to the next
* nxt_conn_io_write() call via c->socket.error. Mirrors the
* TLS path's fail-fast contract; see nxt_openssl_conn_test_error.
*/
c->sent += sb.sent;
nxt_log(task, NXT_LOG_INFO,
"conn write: peer closed mid-response fd:%d sent:%O",
c->socket.fd, sb.sent);
}
Comment on lines +133 to +146
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Similar to the success path, c->write should be updated here to reflect the partial data sent before the error occurred. This ensures the connection state remains consistent if the error_handler or subsequent logging logic inspects the remaining buffers.

    if (sb.sent != 0) {
        /*
         * Pattern D′: route to error_handler immediately when a write
         * returns NXT_ERROR after a partial send (e.g. peer closed
         * mid-response).  Pre-fix, this case fell through to
         * ready_handler and the error was deferred to the next
         * nxt_conn_io_write() call via c->socket.error.  Mirrors the
         * TLS path's fail-fast contract; see nxt_openssl_conn_test_error.
         */
        c->sent += sb.sent;
        c->write = b;
        nxt_log(task, NXT_LOG_INFO,
                "conn write: peer closed mid-response fd:%d sent:%O",
                c->socket.fd, sb.sent);
    }


nxt_fd_event_block_write(engine, &c->socket);

error:
Expand Down
13 changes: 10 additions & 3 deletions src/nxt_router.c
Original file line number Diff line number Diff line change
Expand Up @@ -5892,10 +5892,17 @@ nxt_router_get_mmap_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg)
nxt_assert(port->type == NXT_PROCESS_APP);

if (nxt_slow_path(port->app == NULL)) {
nxt_alert(task, "get_mmap_handler: app == NULL for reply port %PI:%d",
port->pid, port->id);
/*
* Pattern D′: a NULL app pointer here is a benign race during
* worker shutdown / graceful reload (the app freed before its
* reply port was drained), not a corruption. Demoted from
* ALERT so reload-under-load doesn't pollute the log.
*/
nxt_log(task, NXT_LOG_INFO,
"get_mmap_handler: app == NULL for reply port %PI:%d "
"(peer likely shutting down)",
port->pid, port->id);

// FIXME
nxt_port_socket_write(task, port, NXT_PORT_MSG_RPC_ERROR,
-1, msg->port_msg.stream, 0, NULL);

Expand Down
Loading