Skip to content

Commit 5a86bc7

Browse files
committed
quic: zero fd fix on event lib
1 parent 608cc00 commit 5a86bc7

1 file changed

Lines changed: 33 additions & 2 deletions

File tree

lib/roles/quic/ops-quic.c

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,9 +97,40 @@ lws_quic_prefaddr_swap_socket(struct lws *nwsi, const lws_sockaddr46 *to_sa46)
9797
lws_pt_lock(pt, __func__);
9898
if (lws_socket_is_valid(nwsi->desc.sockfd))
9999
__remove_wsi_socket_from_fds(nwsi);
100-
if (lws_socket_is_valid(nwsi->desc.sockfd))
101-
compatible_close(nwsi->desc.sockfd);
100+
101+
/*
102+
* The fd number itself is changing: the event-loop handle that was
103+
* bound to the old fd at accept time cannot be repointed to the new
104+
* fd. For libuv, leaving it in place leaks libuv's per-fd watcher
105+
* entry for the old fd (which was already closed below); when the
106+
* kernel later recycles that fd number, uv_poll_init_socket() trips
107+
* UV_EEXIST on the unrelated new socket. Tear down the old handle
108+
* through the event-lib ops (which also closes the old kernel fd),
109+
* then build a fresh handle for the new fd, exactly as the redirect
110+
* / fd-handoff paths do.
111+
*/
112+
#if defined(LWS_WITH_EVENT_LIBS)
113+
if (cx->event_loop_ops->close_handle_manually)
114+
cx->event_loop_ops->close_handle_manually(nwsi);
115+
else
116+
#endif
117+
{
118+
if (lws_socket_is_valid(nwsi->desc.sockfd))
119+
compatible_close(nwsi->desc.sockfd);
120+
nwsi->desc.sockfd = LWS_SOCK_INVALID;
121+
}
122+
102123
nwsi->desc = new_sock;
124+
125+
#if defined(LWS_WITH_EVENT_LIBS)
126+
if (cx->event_loop_ops->sock_accept)
127+
if (cx->event_loop_ops->sock_accept(nwsi)) {
128+
lws_pt_unlock(pt);
129+
compatible_close(n_fd);
130+
return 1;
131+
}
132+
#endif
133+
103134
if (__insert_wsi_socket_into_fds(cx, nwsi)) {
104135
lws_pt_unlock(pt);
105136
compatible_close(n_fd);

0 commit comments

Comments
 (0)