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

Reply via email to