Skip to content

Commit a1dd26d

Browse files
cirospaciariclaude
andauthored
fix(usockets) fix last_write_failed flag (#25496)
#25361 needs to be merged before this PR ## Summary - Move `last_write_failed` flag from loop-level to per-socket flag for correctness ## Changes - Move `last_write_failed` from `loop->data` to `socket->flags` - More semantically correct since write status is per-socket, not per-loop 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 4.5 <[email protected]>
1 parent 7c06320 commit a1dd26d

File tree

8 files changed

+11
-14
lines changed

8 files changed

+11
-14
lines changed

packages/bun-usockets/src/crypto/openssl.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -417,8 +417,7 @@ void us_internal_update_handshake(struct us_internal_ssl_socket_t *s) {
417417
}
418418
s->handshake_state = HANDSHAKE_PENDING;
419419
s->ssl_write_wants_read = 1;
420-
s->s.context->loop->data.last_write_failed = 1;
421-
420+
s->s.flags.last_write_failed = 1;
422421
return;
423422
}
424423
// success

packages/bun-usockets/src/eventing/libuv.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ void us_poll_init(struct us_poll_t *p, LIBUS_SOCKET_DESCRIPTOR fd,
7171
}
7272

7373
void us_poll_free(struct us_poll_t *p, struct us_loop_t *loop) {
74-
// poll was adopted and dont own uv_poll_t anymore
74+
// poll was resized and dont own uv_poll_t anymore
7575
if(!p->uv_p) {
7676
free(p);
7777
return;

packages/bun-usockets/src/internal/internal.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,8 @@ struct us_socket_flags {
176176
bool adopted: 1;
177177
/* If true, the socket is a TLS socket */
178178
bool is_tls: 1;
179+
/* If true, the last write to this socket failed (would block) */
180+
bool last_write_failed: 1;
179181

180182
} __attribute__((packed));
181183

packages/bun-usockets/src/internal/loop_data.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@ struct us_internal_loop_data_t {
3737
struct us_timer_t *sweep_timer;
3838
int sweep_timer_count;
3939
struct us_internal_async *wakeup_async;
40-
int last_write_failed;
4140
struct us_socket_context_t *head;
4241
struct us_socket_context_t *iterator;
4342
struct us_socket_context_t *closed_context_head;

packages/bun-usockets/src/loop.c

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -391,14 +391,12 @@ void us_internal_dispatch_ready_poll(struct us_poll_t *p, int error, int eof, in
391391
/* The context can change after calling a callback but the loop is always the same */
392392
struct us_loop_t* loop = s->context->loop;
393393
if (events & LIBUS_SOCKET_WRITABLE && !error) {
394-
/* Note: if we failed a write as a socket of one loop then adopted
395-
* to another loop, this will be wrong. Absurd case though */
396-
loop->data.last_write_failed = 0;
394+
s->flags.last_write_failed = 0;
397395
#ifdef LIBUS_USE_KQUEUE
398396
/* Kqueue is one-shot so is not writable anymore */
399397
p->state.poll_type = us_internal_poll_type(p) | ((events & LIBUS_SOCKET_READABLE) ? POLL_TYPE_POLLING_IN : 0);
400398
#endif
401-
399+
402400
s = s->context->on_writable(s);
403401
/* After socket adoption, track the new socket; the old one becomes invalid */
404402
if(s && s->flags.adopted && s->prev) {
@@ -410,7 +408,7 @@ void us_internal_dispatch_ready_poll(struct us_poll_t *p, int error, int eof, in
410408
}
411409

412410
/* If we have no failed write or if we shut down, then stop polling for more writable */
413-
if (!loop->data.last_write_failed || us_socket_is_shut_down(0, s)) {
411+
if (!s->flags.last_write_failed || us_socket_is_shut_down(0, s)) {
414412
us_poll_change(&s->p, loop, us_poll_events(&s->p) & LIBUS_SOCKET_READABLE);
415413
} else {
416414
#ifdef LIBUS_USE_KQUEUE

packages/bun-usockets/src/socket.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -370,7 +370,7 @@ int us_socket_write(int ssl, struct us_socket_t *s, const char *data, int length
370370

371371
int written = bsd_send(us_poll_fd(&s->p), data, length);
372372
if (written != length) {
373-
s->context->loop->data.last_write_failed = 1;
373+
s->flags.last_write_failed = 1;
374374
us_poll_change(&s->p, s->context->loop, LIBUS_SOCKET_READABLE | LIBUS_SOCKET_WRITABLE);
375375
}
376376

@@ -407,7 +407,7 @@ int us_socket_ipc_write_fd(struct us_socket_t *s, const char* data, int length,
407407
int sent = bsd_sendmsg(us_poll_fd(&s->p), &msg, 0);
408408

409409
if (sent != length) {
410-
s->context->loop->data.last_write_failed = 1;
410+
s->flags.last_write_failed = 1;
411411
us_poll_change(&s->p, s->context->loop, LIBUS_SOCKET_READABLE | LIBUS_SOCKET_WRITABLE);
412412
}
413413

src/deps/libuwsockets.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1701,7 +1701,7 @@ size_t uws_req_get_header(uws_req_t *res, const char *lower_case_header,
17011701
{
17021702
us_socket_r s = (us_socket_t *)res;
17031703
if(us_socket_is_closed(s->flags.is_tls, s)) return;
1704-
s->context->loop->data.last_write_failed = 1;
1704+
s->flags.last_write_failed = 1;
17051705
us_poll_change(&s->p, s->context->loop,
17061706
LIBUS_SOCKET_READABLE | LIBUS_SOCKET_WRITABLE);
17071707
}
@@ -1866,7 +1866,7 @@ __attribute__((callback (corker, ctx)))
18661866

18671867
void us_socket_sendfile_needs_more(us_socket_r s) {
18681868
if(us_socket_is_closed(s->flags.is_tls, s)) return;
1869-
s->context->loop->data.last_write_failed = 1;
1869+
s->flags.last_write_failed = 1;
18701870
us_poll_change(&s->p, s->context->loop, LIBUS_SOCKET_READABLE | LIBUS_SOCKET_WRITABLE);
18711871
}
18721872

src/deps/uws/InternalLoopData.zig

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ pub const InternalLoopData = extern struct {
44
sweep_timer: ?*Timer,
55
sweep_timer_count: i32,
66
wakeup_async: ?*us_internal_async,
7-
last_write_failed: i32,
87
head: ?*SocketContext,
98
iterator: ?*SocketContext,
109
closed_context_head: ?*SocketContext,

0 commit comments

Comments
 (0)