Bug 227428 - [curl][Win] very high CPU load on page with WebSocket
Summary: [curl][Win] very high CPU load on page with WebSocket
Status: RESOLVED FIXED
Alias: None
Product: WebKit
Classification: Unclassified
Component: Service Workers (show other bugs)
Version: WebKit Local Build
Hardware: PC Windows 10
: P2 Normal
Assignee: Fujii Hironori
URL:
Keywords: InRadar
Depends on:
Blocks:
 
Reported: 2021-06-27 08:32 PDT by Martijn
Modified: 2021-07-06 00:48 PDT (History)
6 users (show)

See Also:


Attachments
images and documents to reproduce (286.53 KB, application/x-zip-compressed)
2021-06-27 08:32 PDT, Martijn
no flags Details
test case (95 bytes, text/html)
2021-07-05 17:33 PDT, Fujii Hironori
no flags Details
WIP patch (1.17 KB, patch)
2021-07-05 18:20 PDT, Fujii Hironori
no flags Details | Formatted Diff | Diff
WIP patch (547 bytes, patch)
2021-07-05 19:13 PDT, Fujii Hironori
no flags Details | Formatted Diff | Diff
Patch (1.70 KB, patch)
2021-07-05 19:31 PDT, Fujii Hironori
no flags Details | Formatted Diff | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Martijn 2021-06-27 08:32:21 PDT
Created attachment 432351 [details]
images and documents to reproduce

I've build WebKit on windows and I'm playing around with the MiniBrowser. I've made a local html page with some javascript which uses a websocket to connect to a local server (seperate application, using boost). As soon as the websocket is opened, the cpu load goes skyhigh, cpu goes in full speed, 1 core full time busy. I've traced it to some libcurl functions, see attachments.
I've like to help fixing it, but I do need some pointers given my very limited knowledge about webkit.

attached is some information to reproduce the issue:
- html document which includes javascript file
- javascript file which opens websocket and does nothing
- screenshot of task manager
- screenshot of visual studio attached to WebKitNetworkProcess.exe

Starting of the build:

c:\[...]>perl tools\Scripts\build-webkit --wincairo --release
Updating WebKitRequirementsWin64.zip...
Found existing release: v2021.05.26
Seeking latest release from WebKitForWindows/WebKitRequirements...
Found release to download: v2021.05.26
Already up-to-date!
Comment 1 Alexey Proskuryakov 2021-06-28 19:27:45 PDT
FWIW, I cannot reproduce this with macOS Safari (needed to adjust the test to run, app2.js -> app3.js).
Comment 2 Martijn 2021-06-29 10:55:56 PDT
hmm, thats unfortunate, I've tried to debug it a little bit but as soon as I add this:

...
} while (rc == -1 && errno == EINTR);
std::cout << std::chrono::system_clock::now().time_since_epoch().count() / 1000 << " errno: " << errno << " rc: " << rc <<  std::endl;
for (auto& stream : m_streamList.values())
...

in CurlStreamScheduler.cpp, the issue goes away (and nothing shows in any terminal unfortunately, though I added AllocConsole() earlier)

It seems like ::select() is returning constantly, that could maybe explain the hot path as shown in the attachment earlier.

I'm not sure how to continue.
Comment 3 Martijn 2021-07-01 08:58:41 PDT
rc = ::select(maxfd + 1, &readfds, &writefds, &exceptfds, &timeout);
} while (rc == -1 && errno == EINTR);
for (auto& stream : m_streamList.values())

I've increased the timeout value to 2000000 us, my webpage is loaded, websocket connection is made, no data is transfering (checked with wireshark) and I put a breakpoint at the line starting with 'for (...'

the breakpoint triggers instantly and what I see is that readfds has a count of 1, writefds has a count of 0, exceptfds has a count of 1. they all contain the same data:
[0] 1084
[1] 1475739....
rest is all equal to [1] (uninitialized I assume)

continuing the function 'TryToTransfer' results in curl returning CURLE_AGAIN.

I would not expect the readfds to return when no data is transfered, does exceptfds give a clue?
Comment 4 Martijn 2021-07-01 09:16:34 PDT
just wondering:

at the bottom of appendMonitoringFd():

if (maxfd < *socket)
  maxfd = *socket;

at the end the the call, maxfd is -1, and the 'maxfx = *socket' is not executed when I step through with the debugger.

changing it to:

int a = *socket;
if (maxfd < a)
  maxfd = a;

somehow resolved this :s
Comment 5 Radar WebKit Bug Importer 2021-07-04 08:33:18 PDT
<rdar://problem/80150503>
Comment 6 youenn fablet 2021-07-05 08:49:33 PDT
Given this is windows/curl specific, maybe windows port maintainer could help you further investigating the issue.
Comment 7 Fujii Hironori 2021-07-05 17:33:52 PDT
Created attachment 432906 [details]
test case

Thank you very much for testing WinCairo and reporting the bug.
I can reproduce the CPU 100% WebKitNetwork.exe problem. Will check.

And, I found that WinCairo has the critical regression at the moment.
Bug 227694 – [curl][Win] wss: WebSocket doesn't work since r271170
Comment 8 Fujii Hironori 2021-07-05 18:18:53 PDT
curl_socket_t is SOCKET on Windows. SOCKET is UINT_PTR in WinSock.

https://github.com/WebKit/WebKit/blob/eab9b2b8ee9405ca95bb415f5ddf58766afe0159/Source/WebCore/platform/network/curl/CurlStream.cpp#L10

>    if (maxfd < socket)

This condition can't be true.
Comment 9 Fujii Hironori 2021-07-05 18:20:58 PDT
Created attachment 432908 [details]
WIP patch
Comment 10 Fujii Hironori 2021-07-05 19:13:23 PDT
Created attachment 432910 [details]
WIP patch
Comment 11 Fujii Hironori 2021-07-05 19:31:50 PDT
Created attachment 432911 [details]
Patch
Comment 12 Fujii Hironori 2021-07-06 00:48:24 PDT
Comment on attachment 432911 [details]
Patch

Clearing flags on attachment: 432911

Committed r279576 (239407@main): <https://commits.webkit.org/239407@main>
Comment 13 Fujii Hironori 2021-07-06 00:48:28 PDT
All reviewed patches have been landed.  Closing bug.