feat: add UV_LOOP_INTERRUPT_ON_IO_CHANGE option to uv_loop_configure#3308
feat: add UV_LOOP_INTERRUPT_ON_IO_CHANGE option to uv_loop_configure#3308zcbenz wants to merge 2 commits into
Conversation
5d12f3c to
0e1889c
Compare
|
This issue has been automatically marked as stale because it has not had recent activity. Thank you for your contributions. |
|
Bumping to remove the stale label. |
|
Perhaps @cjihrig or @santigimeno might have thoughts as well! |
|
@bnoordhuis @vtjnash may also have thoughts? |
bnoordhuis
left a comment
There was a problem hiding this comment.
LGTM if it works for Electron. I posted some suggestions I'll apply.
|
Failing on Windows here: Line 76 in 96b26b1 |
0c9184d to
805ef15
Compare
|
Thanks for the review, it turns out to be caused by difference between 1.x and 2.x: in 1.x the |
|
The failing test was probably a flake but I'll rerun CI just in case. For posterity: |
|
How does this patch behave in the special use case described in #3234 (comment)? Haven't tested, but looking at the code seems like this patch will still run like a busy poll. |
|
Replying #3299 (comment) here: You described an embedding setup where you poll
A ping-pong to thread B is of course a lot more heavyweight than polling directly in thread A; if this is possible I think #3234 uses less syscalls, if that busy polling behavior is not a problem. |
|
@XeCycle I don't 100% understand your use case so I can't comment much on it. This PR means to fix the problem in #3101, and in this PR I have added a test that should be able to describe the problem in actual code. If you could write a libuv test demonstrating how you are implementing loop integration and what problem you are trying to solve, the discussion would be easier. (And I think it would be required anyway if you want to get a significant change merged) Back to your question, first I think it is important to understand that libuv is an event loop library that means to use as less CPU as possible, even though it involves using heavy operations is not a problem (for example, some async fs APIs are implemented with thread pools). So introducing busy loop into libuv is not desirable, and the loop integration used in If you think there is a better way to fix #3101 without this API, it would be great if you can write a proof of concept similar to |
|
@zcbenz please checkout examples at XeCycle@d9023a7. I based this commit on my #3234. They are Linux-only, and the "outer loop" which embeds the inner libuv loop is a bare-bones minimal event loop using directly
I'm not sure I understood 100% your patch, would you like to take the trouble to solve the busy-looping of |
|
Thanks for the example code, it helps very much understanding the problem, and I think it is a better way to integrate event loops on Linux. However in our use case, we are integrating libuv loop with native GUI message loops, and unlike Linux that almost everything is a fd, on Windows the GUI message loop can not run together with IO message loop, and polling the message loops in separate threads is the only option we have. (On Windows GUI message loop can not be used to listen to events from IOCP, and IOCP APIs can not be used to poll GUI messages.) Also in our project the message loops are created and run by upstream projects (Node.js and Chromium), and we would like to avoid patching the projects when possible, and running message loops in separate threads can perfectly achieve this purpose. So this is why we are doing loop integration via a separate thread. Regarding your use case in And unfortunately #3234 does not fix our problem in Also as your example in But this API has to be explicitly called by users to kick in, so if a user has read the documentation of this API and explicitly called this API, I think it is also user's responsibility to avoid doing the above operation. There are lots of ways to get into busy loop with official libuv APIs, as long as the document is clear I think it should be fine. For example it is simple to get into busy loop with |
Thanks for your explanation, I'm less experienced with Windows. Given this solid reason to do polling in separate threads, I welcome wholeheartedly inclusion of your patch.
Right, and one more word, it is limited to the case when you are not in control of the outer loop and had resorted to polling in another thread. I understand it's a valid use case worth supporting, and my patch does not fix it. As for the busy-loop problem, I admit my case is a synthetic example that is not backed by any real world use cases; but technically it is affected by embedding. Suppose a user has a large code base previously driven by And if we declare such a busy loop is not a problem, may I ask maintainers to give some directions on bringing forward my patch? I think it's a better option to support single-threaded embedding, although not perfect. IMHO a perfect fix would need to fundamentally change our execution order in a loop iteration, and that would break a lot of things so not realistic to be brought into v1.x. |
|
This issue has been automatically marked as stale because it has not had recent activity. Thank you for your contributions. |
|
@zcbenz are you still interested in this? |
|
Yes, and I think we don't have any remaining issue before merging this. |
|
@bnoordhuis is there anything preventing this from being merged? We'd really like to move it forward. |
|
It's a new API and non-trivial so it should get at least one more sign-off from a maintainer. |
63b426f to
6c2605e
Compare
|
This issue has been automatically marked as stale because it has not had recent activity. Thank you for your contributions. |
6c2605e to
0494975
Compare
|
@zcbenz FYI I've been trying to do a similar thing but I've figured out a little different approach which does not need any changes in libuv but it's still arguably a hack I think. in general, I thought I could do wait+re-render in the idle task but that forces timeout to be zero, so I've splitted the whole process into 2 parts - prepare which reads the timeout, waits for GUI events and handles them, and then I start the idle task, which re-renders everything and stops itself again (this is important because then I can read correct timeout again) to read nodejs events I read backend_fd - it's not working yet because I need to add a semaphore there but I think it should generally work because the timeout can only change during prepare task and I know about that so I can tell awaker thread how long it needs to wait. I mean, I'm not saying it's a better solution but maybe it's interesting to know. And maybe we can figure out something even better. |
|
I believe this is fixed now, so this PR is unnecessary |
The hack is still in the electron |
|
Electron tries to read |
|
@vtjnash Unfortunately we still need this patch to make node integration work in Electron. The special thing about Electron is that its main event loop is a GUI event loop, which almost no other libuv users do, and I think that is why you thought this issue was solved. I have written down a detailed explanation of why this patch is needed. I understand this use case is not typical and probably only Electron needs this patch, but on the other hand the number of users running Electron apps is too large that I believe it is worth having this patch in upstream. Why Electron has to poll libuv loop in a background threadElectron is a GUI app, whose main thread must run the GUI event loop to keep responsive, and on Windows and macOS unfortunately the GUI event loop can not run together with IO event loop (which is used by libuv). This is a Windows GUI event loop: while(GetMessage(&Msg, NULL, 0, 0) > 0) {
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}And this is a Windows IO event loop: while (true) {
OVERLAPPED* overlapped;
ULONG_PTR completionKey;
DWORD bytesTransferred;
GetQueuedCompletionStatus(completionPort, &bytesTransferred, &completionKey, &overlapped, INFINITE);
}The Thus in Electron, we create a polling fd in background thread to poll libuv's backend fd, and whenever there is a new IO event, the GUI event loop will be notified to run libuv event loop in the main thread to handle the IO event. // In background thread
while (WaitForSignalFromMainThread()) {
PollEventsInBackgroundThread();
PostMessageToMainThread();
}// In main thread
while(GetMessage() > 0) {
if (IsIOMessageFromBackgroundThread()) {
uv_run_loop_once();
SendSignalToBackgroundThreadToContinuePolling();
} else {
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
}Problem with background thread pollingAs mentioned above, Electron creates a new fd (let's call it int backend_fd = uv_backend_fd(uv_loop_);
struct epoll_event ev = {0};
ev.events = EPOLLIN;
ev.data.fd = backend_fd;
epoll_ctl(epoll_, EPOLL_CTL_ADD, backend_fd, &ev);And then polls the void PollEventsInBackgroundThread() {
int timeout = uv_backend_timeout(uv_loop_);
int r;
do {
struct epoll_event ev;
r = epoll_wait(epoll_, &ev, 1, timeout);
} while (r == -1 && errno == EINTR);
}(The implementation calls However the For example, when users call Similarly, when users call How to solve the problemTo solve the problem, we force the This is what this patch does, by adding a new The performance however does not really matter in Electron, the node integration happens in the GUI thread where it is not supposed to do any heavy operations at all, so a little performance penalty is totally acceptable in exchange of full Node support. |
|
What about something like this: (sorry this is pseudocode and I didn't test it, I hope you can get my idea) I guess this should work on Linux, but it depends on that I can have a thread blocked in epoll_wait, and at the same time modify its (kernel) watch list in another thread. So if I need to call uv_run to sync uv watch list to the kernel watch list, just do it here, no need to stop the polling thread beforehand. And tell the polling thread that timeout may have changed (I can cache the target time to avoid some messaging overhead). But, allow me to reiterate, this depends on that in epoll_wait(2):
I don't know how IOCP behaves, so I'm not sure whether this can work for you. |
|
@XeCycle Thanks for the pseudocode and it totally makes sense, and I think it can solve the problem without this patch. But with this approach Electron apps are already famous for being resource hogs, I think having a patch in libuv to save the resources should be worthwhile. |
|
This is where you would use |
Yes, but Electron is depending on that being safe anyways, otherwise it would have had a far worse data race on its hands by letting that epoll_wait call exist at the same time as libuv was running on another thread. But as you saw in
This is already how it is implemented, so I fail to see why this would become an issue now: https://github.com/electron/electron/blob/e1d63794e5ce74006188ed2b7f1c35b5793caf36/shell/common/node_bindings.cc#L742 |
|
Some improvements to your pseudo-code. If you squint at the existing nodejs code, I think you will find it is already nearly identical to this, and only needs a couple tweaks: __Atomic(bool) uv_run_needed;
void gui_loop() {
while (wait_gui_event(uv_backend_timeout(loop))) {
process_gui_events();
if (uv_run_needed || uv_backend_timeout(loop) == 0) {
// this conditional is optional, but can be good for UI performance to avoid spurious epoll_wait syscall
// it can also be a while loop, depending on how heavily you want to prioritize uv over gui events
uv_run(loop, UV_RUN_NOWAIT);
uv_run_needed = false;
std::lock_guard<>() pthread_cond_notify();
}
}
}
void epoll_loop() {
while (1) {
epoll_wait();
uv_run_needed = true;
gui_loop_notify();
std::lock_guard<>() if (uv_run_needed)
pthread_cond_wait();
}
}This should fix the data-race on timeout and avoids the spurious thread wakeup on timeouts. In exchange, it uses an explicit seq-cst fence (instead of relying on it being probably implied by epoll) on |
After writing some tests, it seems that you are right, the backend thread does not need an explicit interruption to get notified of events of newly added fds. But somehow this does not match what I observed in Electron: without my patch, callbacks of async APIs like
The referenced I have a much simplified version of the node integration code, which should be more readable: And the void NodeIntegration::WakeupMainThread() {
PostTask([this] {
this->UvRunOnce();
});
}
Thanks for the code, I think in theory it implements the event loop integration in a very clean way. But when trying to implement it in actual code, I found that the biggest problem is that the For GTK apps in Linux the And even if all the underlying system APIs do support timeout parameter, I found that Chromium's message loop class does not support passing parameter. if I have to choose between a rather large Chromium patch and a simple libuv patch, I will have to choose the latter. So in real code to make timeouts work I have to set a timer and keep updating it in every gui message loop iteration: void gui_loop() {
while (wait_gui_event()) {
process_gui_events();
if (uv_run_needed || uv_backend_timeout(loop) == 0) {
...
}
clearTimeout(timer);
timer = setTimeout(uv_backend_timeout(loop));
}
}Or degrade void gui_loop() {
while (wait_gui_event()) {
process_gui_events();
uv_run(loop, UV_RUN_NOWAIT);
}
}But still I'm not comfortable with the above versions though, either of them has to make tremendous useless calls when we could just make necessary calls by adding a small patch in libuv. |
|
I know Gtk supports this timeout, because I integrated it years ago this way: https://github.com/JuliaGraphics/Gtk.jl/blob/881fdce8eb5a8bce2f1a846f79ac7142177e5b2a/src/GLib/signals.jl#L299 If Chromium is bad at clearTimeout, you can coalesce those. In nodejs / libuv, normally that would be done with a prepare hook that starts the necessary timeout before the poll call. I don't know the equivalent for Chromium. |
|
Thanks for the references, there are quite a lot of new information and I'll give them a try. |
Pending work may be either (on any platform) pending_queue callbacks or (on unix) watcher_queue handles to add to the io poll object. Previously, we might have gotten somewhat stuck if the user caused an event to be added to one of these in the idle or prepare callbacks, or was embedding libuv. Refs: libuv/libuv#3234 Refs: libuv/libuv#3101 Refs: libuv/libuv#3308
Pending work may be either (on any platform) pending_queue callbacks or (on unix) watcher_queue handles to add to the io poll object. Previously, we might have gotten somewhat stuck if the user caused an event to be added to one of these in the idle or prepare callbacks, or was embedding libuv. Refs: libuv/libuv#3234 Refs: libuv/libuv#3101 Refs: libuv/libuv#3308
Ref: libuv/libuv#3308 Co-Authored-By: Claude <noreply@anthropic.com>
Ref: libuv/libuv#3308 Co-Authored-By: Claude <noreply@anthropic.com>
Ref: libuv/libuv#3308 Co-Authored-By: Claude <noreply@anthropic.com>
Ref: libuv/libuv#3308 Co-Authored-By: Claude <noreply@anthropic.com> (cherry picked from commit 31b7fb0)
* chore: bump node in DEPS to v24.16.0
* chore: remove upstreamed patch
Node.js restored fs patchability in the ESM loader upstream, making
the fix_lazyload_fs_in_esm_loaders_to_apply_asar_patches.patch
obsolete (the patch's exact change is now in lib/internal/modules/
esm/{load,resolve,translators}.js).
Ref: nodejs/node#62835
Co-Authored-By: Claude <noreply@anthropic.com>
(cherry picked from commit 72638db)
* fix(patch): re-add experimental_fetch member after upstream cleanup
Upstream removed the experimental_fetch field from EnvironmentOptions,
but Electron's patch still registers --experimental-fetch as a CLI
option bound to that field. Re-add the member so the option compiles.
Ref: nodejs/node#62759
Co-Authored-By: Claude <noreply@anthropic.com>
(cherry picked from commit 6fd9370)
* fix(patch): cast const away when freeing uv_cpu_info_t.model
libuv 1.52.1 typed uv_cpu_info_t.model as const char*, but uv__free
takes void*. Electron builds with -Werror,-Wincompatible-pointer-types-
discards-qualifiers, so add a cast. The memory is allocated via strdup
so the cast is safe.
Ref: nodejs/node#61829
Co-Authored-By: Claude <noreply@anthropic.com>
(cherry picked from commit 90d1009)
* fix(patch): silence sign-compare warning in sessionVarintGetSafe
Cast int nBuf to size_t when comparing with sizeof(aCopy) so the
bundled sqlite3 amalgamation compiles under -Werror,-Wsign-compare.
Ref: nodejs/node#62699
Co-Authored-By: Claude <noreply@anthropic.com>
* test: move root package.json aside in node spec runner
third_party/electron_node lives under Chromium's src/, whose package.json
("type": "module") is always an ancestor of the Node.js test tree. Upstream
assumes no package.json sits above the tests, so that ancestor changes how
test files and fixtures resolve their module type: it disables module-syntax
detection (breaking test-compile-cache-typescript-esm) and emits
MODULE_TYPELESS_PACKAGE_JSON warnings that break tests asserting clean stderr
(test-esm-detect-ambiguous, test-esm-import-meta-main-eval,
test-output-coverage-with-mock).
Move src/package.json aside for the duration of the run so the environment
matches upstream exactly, then restore it. The original is kept in a sibling
backup file so an interrupted/killed run self-heals on the next invocation
rather than leaving src/package.json missing.
Ref: Unable to locate reference
Co-Authored-By: Claude <noreply@anthropic.com>
(cherry picked from commit 29abd0c)
* fix(patch): mark test-macos-app-sandbox as flaky
The test copies the Electron binary into a standalone .app bundle and
code-signs it; under parallel suite runs this races with dyld resolving
the Electron Framework rpath and intermittently aborts (SIGABRT). It
passes reliably when run alone. Mark it flaky so flakes don't fail CI.
Ref: Unable to locate reference
Co-Authored-By: Claude <noreply@anthropic.com>
(cherry picked from commit 3853529)
* test: disable test-tls-set-default-ca-certificates-extra-override
setDefaultCACertificates() round-trips the default CA set through
BoringSSL's X509_STORE, which dedups a duplicate-subject root (DigiCert
Global Root CA) that OpenSSL keeps. The set therefore loses one cert on
re-add (149 -> 148), so the test's assertEqualCerts round-trip check
fails under Electron's BoringSSL. The sibling -recovery test is disabled
for the same reason.
Ref: nodejs/node#58822
Co-Authored-By: Claude <noreply@anthropic.com>
(cherry picked from commit 3dbc596)
* fix(patch): mark test-runner watch tests as flaky
test-run-watch-repeatedly, test-run-watch-run-duration and
test-run-watch-without-file race under parallel suite load: the watcher
fires an extra re-run before the assertion, so the expected single-run
output ("tests 1") arrives with accumulated subtests. All three pass in
isolation.
Ref: nodejs/node#44898
Co-Authored-By: Claude <noreply@anthropic.com>
(cherry picked from commit 0f9c327)
* chore(patches): update libuv const-cast patch management
Combine the Windows libuv cpu_info const-cast update into the existing
chore_cast_const_away_when_freeing_uv_cpu_info_t_model.patch and keep
a single patch-management commit for the final exported patch series.
Co-Authored-By: Claude <noreply@anthropic.com>
(cherry picked from commit c590614)
* fix(patch): add UV_LOOP_INTERRUPT_ON_IO_CHANGE option
Ref: libuv/libuv#3308
Co-Authored-By: Claude <noreply@anthropic.com>
* chore: update patches (trivial only)
Co-Authored-By: Claude <noreply@anthropic.com>
* chore: update patches
Co-Authored-By: Claude <noreply@anthropic.com>
* fix(patch): adapt GetIsolate removal for the inspector NetworkAgent
Adapts api_remove_deprecated_getisolate.patch for the inspector NetworkAgent:
adapt the GetIsolate removal to the NetworkAgent member helpers, qualify the
v8 Maybe helpers in network_agent, and drop duplicate inspector helper
definitions.
Ref: nodejs/node#62162
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* fix(patch): guard vm contextual-store strict assertion for Chromium's V8
test-vm-global-contextual-store was added upstream in nodejs/node#62571. It
asserts that an undeclared strict-mode contextual store (`"use strict"; z = 42`)
throws a ReferenceError. Chromium's V8 removed
v8::PropertyCallbackInfo<T>::This(), so Electron's contextify setter cannot
distinguish a contextual store from an explicit `globalThis.x = v` store; it
keeps the original behavior (writing to the sandbox) so explicit global stores
in vm modules keep working (test-vm-module-referrer-realm). Guard the
strict-mode ReferenceError assertion in the new test under Electron.
Ref: nodejs/node#62571
Ref: nodejs/node#60616
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
---------
Co-authored-by: electron-roller[bot] <84116207+electron-roller[bot]@users.noreply.github.com>
Co-authored-by: John Kleinschmidt <jkleinsc@electronjs.org>
Co-authored-by: Claude <noreply@anthropic.com>
* chore: bump node in DEPS to v24.16.0
* chore: remove upstreamed patch
Node.js restored fs patchability in the ESM loader upstream, making
the fix_lazyload_fs_in_esm_loaders_to_apply_asar_patches.patch
obsolete (the patch's exact change is now in lib/internal/modules/
esm/{load,resolve,translators}.js).
Ref: nodejs/node#62835
Co-Authored-By: Claude <noreply@anthropic.com>
(cherry picked from commit 72638db)
(cherry picked from commit 0409547)
* fix(patch): re-add experimental_fetch member after upstream cleanup
Upstream removed the experimental_fetch field from EnvironmentOptions,
but Electron's patch still registers --experimental-fetch as a CLI
option bound to that field. Re-add the member so the option compiles.
Ref: nodejs/node#62759
Co-Authored-By: Claude <noreply@anthropic.com>
(cherry picked from commit 6fd9370)
(cherry picked from commit 46b28d2)
* fix(patch): cast const away when freeing uv_cpu_info_t.model
libuv 1.52.1 typed uv_cpu_info_t.model as const char*, but uv__free
takes void*. Electron builds with -Werror,-Wincompatible-pointer-types-
discards-qualifiers, so add a cast. The memory is allocated via strdup
so the cast is safe.
Ref: nodejs/node#61829
Co-Authored-By: Claude <noreply@anthropic.com>
(cherry picked from commit 90d1009)
(cherry picked from commit 07827c6)
* fix(patch): silence sign-compare warning in sessionVarintGetSafe
Cast int nBuf to size_t when comparing with sizeof(aCopy) so the
bundled sqlite3 amalgamation compiles under -Werror,-Wsign-compare.
Ref: nodejs/node#62699
Co-Authored-By: Claude <noreply@anthropic.com>
(cherry picked from commit 379d109)
* test: move root package.json aside in node spec runner
third_party/electron_node lives under Chromium's src/, whose package.json
("type": "module") is always an ancestor of the Node.js test tree. Upstream
assumes no package.json sits above the tests, so that ancestor changes how
test files and fixtures resolve their module type: it disables module-syntax
detection (breaking test-compile-cache-typescript-esm) and emits
MODULE_TYPELESS_PACKAGE_JSON warnings that break tests asserting clean stderr
(test-esm-detect-ambiguous, test-esm-import-meta-main-eval,
test-output-coverage-with-mock).
Move src/package.json aside for the duration of the run so the environment
matches upstream exactly, then restore it. The original is kept in a sibling
backup file so an interrupted/killed run self-heals on the next invocation
rather than leaving src/package.json missing.
Ref: Unable to locate reference
Co-Authored-By: Claude <noreply@anthropic.com>
(cherry picked from commit 29abd0c)
(cherry picked from commit 3190c99)
* fix(patch): mark test-macos-app-sandbox as flaky
The test copies the Electron binary into a standalone .app bundle and
code-signs it; under parallel suite runs this races with dyld resolving
the Electron Framework rpath and intermittently aborts (SIGABRT). It
passes reliably when run alone. Mark it flaky so flakes don't fail CI.
Ref: Unable to locate reference
Co-Authored-By: Claude <noreply@anthropic.com>
(cherry picked from commit 3853529)
(cherry picked from commit 2dfc1ae)
* test: disable test-tls-set-default-ca-certificates-extra-override
setDefaultCACertificates() round-trips the default CA set through
BoringSSL's X509_STORE, which dedups a duplicate-subject root (DigiCert
Global Root CA) that OpenSSL keeps. The set therefore loses one cert on
re-add (149 -> 148), so the test's assertEqualCerts round-trip check
fails under Electron's BoringSSL. The sibling -recovery test is disabled
for the same reason.
Ref: nodejs/node#58822
Co-Authored-By: Claude <noreply@anthropic.com>
(cherry picked from commit 3dbc596)
(cherry picked from commit 44f4094)
* fix(patch): mark test-runner watch tests as flaky
test-run-watch-repeatedly, test-run-watch-run-duration and
test-run-watch-without-file race under parallel suite load: the watcher
fires an extra re-run before the assertion, so the expected single-run
output ("tests 1") arrives with accumulated subtests. All three pass in
isolation.
Ref: nodejs/node#44898
Co-Authored-By: Claude <noreply@anthropic.com>
(cherry picked from commit 0f9c327)
(cherry picked from commit 792e1e5)
* chore(patches): update libuv const-cast patch management
Combine the Windows libuv cpu_info const-cast update into the existing
chore_cast_const_away_when_freeing_uv_cpu_info_t_model.patch and keep
a single patch-management commit for the final exported patch series.
Co-Authored-By: Claude <noreply@anthropic.com>
(cherry picked from commit c590614)
(cherry picked from commit 0506b64)
* fix(patch): add UV_LOOP_INTERRUPT_ON_IO_CHANGE option
Ref: libuv/libuv#3308
Co-Authored-By: Claude <noreply@anthropic.com>
(cherry picked from commit 31b7fb0)
* fix(patch): update GetIsolate removal for inspector NetworkAgent refactor
Upstream refactored the inspector network agent helpers into
NetworkAgent:: methods, shifting where context->GetIsolate() appeared
and reorganizing node_contextify's PropertyDefinerCallback. Re-applied
the deprecated context->GetIsolate() -> v8::Isolate::GetCurrent()
replacements to the new structure.
Ref: nodejs/node#62162
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* fix: drop dangling .patches entries for non-existent patch files
The cherry-pick of the cast-const fix (343078bf01) erroneously added
four entries to patches/node/.patches that reference patch files which
were never part of the 41-x-y branch (externalpointertypetag, thinlto
symbol preservation, v8 code cache, and startup snapshot generation).
The missing files caused `e sync` to abort while reading patches.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* chore: update patches (trivial only)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* test: disable test-vm-global-contextual-store
This new upstream test asserts that a strict-mode store to an undeclared
global in a vm context throws ReferenceError. Chromium's V8 contextify
global-proxy interceptor instead creates the property, so the assertion
is fundamentally incompatible with Electron's V8 and cannot be guarded
to pass.
Ref: nodejs/node#62571
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
---------
Co-authored-by: electron-roller[bot] <84116207+electron-roller[bot]@users.noreply.github.com>
Co-authored-by: John Kleinschmidt <jkleinsc@electronjs.org>
Co-authored-by: Claude <noreply@anthropic.com>
Close #3101.
Refs #3299, #3234, #1921, #1565, #1568.
When integrating an uv event loop with other event loops, we usually poll the backend fd in a separate thread and do
uv_runwhenever there is an event triggered. However in libuv some types of changes to handles do not trigger events on the backend fd (for example starting new timers), and the polling of backend fd will still use old timeout and old event flags, and this would cause problem like, Node'ssetTimeoutnot working in Electron.This PR adds a
UV_LOOP_INTERRUPT_ON_IO_CHANGEoption touv_loop_configurethat, with it the loop will be interrupted whenever a new IO event has been added or changed, and the embedders will get a chance to restart the polling of the backend.Electron has been using this technique for years and it has been working well.
/cc @bnoordhuis @vtjnash