Branch: refs/heads/main
Home: https://github.com/WebKit/WebKit
Commit: f391b9f442fc44d4d93ed3b20733202d154b0a79
https://github.com/WebKit/WebKit/commit/f391b9f442fc44d4d93ed3b20733202d154b0a79
Author: Chris Dumez <[email protected]>
Date: 2026-05-22 (Fri, 22 May 2026)
Changed paths:
A
LayoutTests/http/tests/websocket/tests/hybi/handshake-fail-with-200-ok_wsh.py
A
LayoutTests/http/tests/websocket/tests/hybi/worker-handshake-failure-cleanup-expected.txt
A
LayoutTests/http/tests/websocket/tests/hybi/worker-handshake-failure-cleanup.html
M Source/WebCore/page/SocketProvider.h
M Source/WebCore/testing/Internals.cpp
M Source/WebCore/testing/Internals.h
M Source/WebCore/testing/Internals.idl
M Source/WebKit/NetworkProcess/NetworkConnectionToWebProcess.cpp
M Source/WebKit/NetworkProcess/NetworkConnectionToWebProcess.h
M Source/WebKit/NetworkProcess/NetworkConnectionToWebProcess.messages.in
M Source/WebKit/WebProcess/Network/WebSocketChannel.cpp
M Source/WebKit/WebProcess/Network/WebSocketChannel.h
M Source/WebKit/WebProcess/Network/WebSocketProvider.cpp
M Source/WebKit/WebProcess/Network/WebSocketProvider.h
Log Message:
-----------
NetworkSocketChannel leaks when a worker WebSocket is closed by the server
https://bugs.webkit.org/show_bug.cgi?id=315342
rdar://130167032
Reviewed by Youenn Fablet.
When a worker-scoped WebSocket is closed by the peer, the
WebProcess-side WebKit::WebSocketChannel never sends the Close IPC to
the network process, so NetworkSocketChannel sits in State::Closing
forever and its underlying NSURLSessionWebSocketTask leaks.
The chain on a peer-initiated close (network process delivers DidClose):
WebSocketChannel::didClose (main thread)
-> client->didClose, where client is WorkerThreadableWebSocketChannel::Peer
-> Peer::didClose sets m_mainWebSocketChannel = nullptr
(drops the only strong ref to WebKit::WebSocketChannel)
-> WebSocketChannel::didClose returns
-> protectedThis goes out of scope, last ref drops
-> ~WebSocketChannel runs (currently does not send Close)
The path that *would* send the Close IPC is
Peer::~Peer -> m_mainWebSocketChannel->disconnect(), but
m_mainWebSocketChannel was already nulled in Peer::didClose, so ~Peer
is a no-op. The worker-side WebSocket::didClose handler eventually
calls socket.m_channel->disconnect(), but in the worker case
m_channel is the WorkerThreadableWebSocketChannel, whose Bridge::disconnect
only nullifies local state and does not send any IPC.
The document-scoped path is unaffected because there
WebSocket::m_channel is the WebKit::WebSocketChannel directly, and
WebSocket::didClose's task does m_channel->disconnect() against it,
which sends the IPC explicitly.
Fix this by sending the Close IPC from ~WebSocketChannel when none of
the explicit close/disconnect paths sent it. A new m_needsToCallClose
flag is set to true in WebSocketChannel::connect() once the
CreateSocketChannel IPC has actually been sent (so connect() failures
that returned early don't leave a stale flag), and is cleared whenever
close()/fail()/disconnect() send a Close IPC. The destructor then
sends Close only when the flag is still set, ensuring a single Close
IPC per network-process channel and none for channels the network
process never knew about.
TEST: http/tests/websocket/tests/hybi/worker-handshake-failure-cleanup.html
*
LayoutTests/http/tests/websocket/tests/hybi/handshake-fail-with-200-ok_wsh.py:
Added.
(web_socket_do_extra_handshake):
(web_socket_transfer_data):
*
LayoutTests/http/tests/websocket/tests/hybi/worker-handshake-failure-cleanup-expected.txt:
Added.
*
LayoutTests/http/tests/websocket/tests/hybi/worker-handshake-failure-cleanup.html:
Added.
* Source/WebCore/page/SocketProvider.h:
* Source/WebCore/testing/Internals.cpp:
(WebCore::Internals::numberOfWebSocketChannelsInNetworkProcess):
* Source/WebCore/testing/Internals.h:
* Source/WebCore/testing/Internals.idl:
* Source/WebKit/NetworkProcess/NetworkConnectionToWebProcess.cpp:
(WebKit::NetworkConnectionToWebProcess::countWebSocketChannelsForTesting):
* Source/WebKit/NetworkProcess/NetworkConnectionToWebProcess.h:
* Source/WebKit/NetworkProcess/NetworkConnectionToWebProcess.messages.in:
* Source/WebKit/WebProcess/Network/WebSocketChannel.cpp:
(WebKit::WebSocketChannel::~WebSocketChannel):
(WebKit::WebSocketChannel::connect):
(WebKit::WebSocketChannel::close):
(WebKit::WebSocketChannel::fail):
(WebKit::WebSocketChannel::disconnect):
* Source/WebKit/WebProcess/Network/WebSocketChannel.h:
* Source/WebKit/WebProcess/Network/WebSocketProvider.cpp:
(WebKit::WebSocketProvider::countWebSocketChannelsForTesting):
* Source/WebKit/WebProcess/Network/WebSocketProvider.h:
Canonical link: https://commits.webkit.org/313770@main
To unsubscribe from these emails, change your notification settings at
https://github.com/WebKit/WebKit/settings/notifications