Skip to content

Commit e7b8f0c

Browse files
committed
Fix listener publication race in socket driver
That commit fixed the close-time double-unlink/use-after-free race in generic_unix listener teardown. This change addresses a separate race in listener registration, where a listener could become visible to the event loop before socket_data published the corresponding pointer. Both fixes are needed; this patch complements the earlier teardown fix rather than replacing it. Fix a race in the generic_unix socket driver where newly created listeners were registered in the global listener list before the corresponding socket_data->{active,passive}_listener pointer was published. If the event loop processed the listener in that window, the callback could consume, free, or replace the listener before the socket driver stored the pointer. The later assignment then left socket_data pointing at stale listener memory, which could surface as random hangs or corruption in gen_tcp tests, including timeouts waiting for the server helper process to start. Publish the listener pointer before calling sys_register_listener in all affected paths: active UDP receive listener setup active TCP receive listener setup passive recv/recvfrom listener setup accept listener setup This complements the earlier close-path fix by removing another generic_unix listener lifecycle race. Signed-off-by: Peter M <petermm@gmail.com>
1 parent 34a3287 commit e7b8f0c

File tree

1 file changed

+12
-4
lines changed

1 file changed

+12
-4
lines changed

src/platforms/generic_unix/lib/socket_driver.c

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -255,8 +255,10 @@ static term init_udp_socket(Context *ctx, SocketDriverData *socket_data, term pa
255255
listener->base.handler = active_recvfrom_callback;
256256
listener->buf_size = socket_data->buffer;
257257
listener->process_id = ctx->process_id;
258-
sys_register_listener(glb, &listener->base);
258+
// Publish the pointer before registering so callbacks cannot win
259+
// the race and leave socket_data pointing at a stale listener.
259260
socket_data->active_listener = listener;
261+
sys_register_listener(glb, &listener->base);
260262
}
261263
}
262264
return ret;
@@ -340,8 +342,10 @@ static term init_client_tcp_socket(Context *ctx, SocketDriverData *socket_data,
340342
listener->base.handler = active_recv_callback;
341343
listener->buf_size = socket_data->buffer;
342344
listener->process_id = ctx->process_id;
343-
sys_register_listener(glb, &listener->base);
345+
// Publish the pointer before registering so callbacks cannot win
346+
// the race and leave socket_data pointing at a stale listener.
344347
socket_data->active_listener = listener;
348+
sys_register_listener(glb, &listener->base);
345349
}
346350
}
347351
return ret;
@@ -1017,8 +1021,10 @@ static void do_recv(Context *ctx, term pid, term ref, term length, term timeout,
10171021
listener->length = term_to_int(length);
10181022
listener->buffer = socket_data->buffer;
10191023
listener->ref_ticks = term_to_ref_ticks(ref);
1020-
sys_register_listener(glb, &listener->base);
1024+
// Publish the pointer before registering so callbacks cannot win
1025+
// the race and leave socket_data pointing at a stale listener.
10211026
socket_data->passive_listener = listener;
1027+
sys_register_listener(glb, &listener->base);
10221028
}
10231029

10241030
void socket_driver_do_recvfrom(Context *ctx, term pid, term ref, term length, term timeout)
@@ -1119,8 +1125,10 @@ void socket_driver_do_accept(Context *ctx, term pid, term ref, term timeout)
11191125
listener->length = 0;
11201126
listener->buffer = 0;
11211127
listener->ref_ticks = term_to_ref_ticks(ref);
1122-
sys_register_listener(glb, &listener->base);
1128+
// Publish the pointer before registering so callbacks cannot win
1129+
// the race and leave socket_data pointing at a stale listener.
11231130
socket_data->passive_listener = listener;
1131+
sys_register_listener(glb, &listener->base);
11241132
}
11251133

11261134
static NativeHandlerResult socket_consume_mailbox(Context *ctx)

0 commit comments

Comments
 (0)