chore: update libuv patch for event loop integration (#31647)
* chore: update libuv patch for loop integration * chore: update patches Co-authored-by: PatchUp <73610968+patchup[bot]@users.noreply.github.com>
This commit is contained in:
parent
6b66fea67d
commit
4e66b072da
10 changed files with 509 additions and 94 deletions
|
@ -1,5 +1,4 @@
|
||||||
refactor_alter_child_process_fork_to_use_execute_script_with.patch
|
refactor_alter_child_process_fork_to_use_execute_script_with.patch
|
||||||
feat_add_uv_loop_watcher_queue_code.patch
|
|
||||||
feat_initialize_asar_support.patch
|
feat_initialize_asar_support.patch
|
||||||
expose_get_builtin_module_function.patch
|
expose_get_builtin_module_function.patch
|
||||||
build_add_gn_build_files.patch
|
build_add_gn_build_files.patch
|
||||||
|
@ -42,3 +41,4 @@ unix_remove_uv_cloexec_ioctl_3515.patch
|
||||||
process_simplify_uv_write_int_calls_3519.patch
|
process_simplify_uv_write_int_calls_3519.patch
|
||||||
macos_don_t_use_thread-unsafe_strtok_3524.patch
|
macos_don_t_use_thread-unsafe_strtok_3524.patch
|
||||||
process_fix_hang_after_note_exit_3521.patch
|
process_fix_hang_after_note_exit_3521.patch
|
||||||
|
feat_add_uv_loop_interrupt_on_io_change_option_to_uv_loop_configure.patch
|
||||||
|
|
|
@ -0,0 +1,503 @@
|
||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Cheng Zhao <zcbenz@gmail.com>
|
||||||
|
Date: Mon, 31 Jan 2022 20:56:58 +0900
|
||||||
|
Subject: feat: add UV_LOOP_INTERRUPT_ON_IO_CHANGE option to uv_loop_configure
|
||||||
|
|
||||||
|
https://github.com/libuv/libuv/pull/3308
|
||||||
|
|
||||||
|
diff --git a/deps/uv/docs/src/loop.rst b/deps/uv/docs/src/loop.rst
|
||||||
|
index 0f5ddfb3ca21b7e5b38d0a4ce4b9e77387597199..ba815202fb157aa82859ec0518523cf6f2ec6ba1 100644
|
||||||
|
--- a/deps/uv/docs/src/loop.rst
|
||||||
|
+++ b/deps/uv/docs/src/loop.rst
|
||||||
|
@@ -73,7 +73,15 @@ API
|
||||||
|
|
||||||
|
This option is necessary to use :c:func:`uv_metrics_idle_time`.
|
||||||
|
|
||||||
|
+ - UV_LOOP_INTERRUPT_ON_IO_CHANGE: Interrupt the loop whenever a new IO
|
||||||
|
+ event has been added or changed.
|
||||||
|
+
|
||||||
|
+ This option is usually when implementing event loop integration, to make
|
||||||
|
+ the polling of backend fd interrupt to recognize the changes of IO events.
|
||||||
|
+
|
||||||
|
.. versionchanged:: 1.39.0 added the UV_METRICS_IDLE_TIME option.
|
||||||
|
+ .. versionchanged:: 1.43.0 added the UV_LOOP_INTERRUPT_ON_IO_CHANGE option.
|
||||||
|
+
|
||||||
|
|
||||||
|
.. c:function:: int uv_loop_close(uv_loop_t* loop)
|
||||||
|
|
||||||
|
diff --git a/deps/uv/include/uv.h b/deps/uv/include/uv.h
|
||||||
|
index 606083c87de5790d7e66fc34aeaae9a58acb8ef4..824b0b77cf5f0a46dcb3855c44ac73faaba2055f 100644
|
||||||
|
--- a/deps/uv/include/uv.h
|
||||||
|
+++ b/deps/uv/include/uv.h
|
||||||
|
@@ -252,7 +252,8 @@ typedef struct uv_statfs_s uv_statfs_t;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
UV_LOOP_BLOCK_SIGNAL = 0,
|
||||||
|
- UV_METRICS_IDLE_TIME
|
||||||
|
+ UV_METRICS_IDLE_TIME,
|
||||||
|
+ UV_LOOP_INTERRUPT_ON_IO_CHANGE
|
||||||
|
} uv_loop_option;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
diff --git a/deps/uv/src/unix/async.c b/deps/uv/src/unix/async.c
|
||||||
|
index e1805c323795e5b0c465d80100eebeb7bf838caa..dd4358c0cdaa97ba8fadf4d9755993803beddd18 100644
|
||||||
|
--- a/deps/uv/src/unix/async.c
|
||||||
|
+++ b/deps/uv/src/unix/async.c
|
||||||
|
@@ -38,7 +38,6 @@
|
||||||
|
#include <sys/eventfd.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
-static void uv__async_send(uv_loop_t* loop);
|
||||||
|
static int uv__async_start(uv_loop_t* loop);
|
||||||
|
|
||||||
|
|
||||||
|
@@ -70,7 +69,7 @@ int uv_async_send(uv_async_t* handle) {
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* Wake up the other thread's event loop. */
|
||||||
|
- uv__async_send(handle->loop);
|
||||||
|
+ uv__loop_interrupt(handle->loop);
|
||||||
|
|
||||||
|
/* Tell the other thread we're done. */
|
||||||
|
if (cmpxchgi(&handle->pending, 1, 2) != 1)
|
||||||
|
@@ -165,40 +164,6 @@ static void uv__async_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
-static void uv__async_send(uv_loop_t* loop) {
|
||||||
|
- const void* buf;
|
||||||
|
- ssize_t len;
|
||||||
|
- int fd;
|
||||||
|
- int r;
|
||||||
|
-
|
||||||
|
- buf = "";
|
||||||
|
- len = 1;
|
||||||
|
- fd = loop->async_wfd;
|
||||||
|
-
|
||||||
|
-#if defined(__linux__)
|
||||||
|
- if (fd == -1) {
|
||||||
|
- static const uint64_t val = 1;
|
||||||
|
- buf = &val;
|
||||||
|
- len = sizeof(val);
|
||||||
|
- fd = loop->async_io_watcher.fd; /* eventfd */
|
||||||
|
- }
|
||||||
|
-#endif
|
||||||
|
-
|
||||||
|
- do
|
||||||
|
- r = write(fd, buf, len);
|
||||||
|
- while (r == -1 && errno == EINTR);
|
||||||
|
-
|
||||||
|
- if (r == len)
|
||||||
|
- return;
|
||||||
|
-
|
||||||
|
- if (r == -1)
|
||||||
|
- if (errno == EAGAIN || errno == EWOULDBLOCK)
|
||||||
|
- return;
|
||||||
|
-
|
||||||
|
- abort();
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
-
|
||||||
|
static int uv__async_start(uv_loop_t* loop) {
|
||||||
|
int pipefd[2];
|
||||||
|
int err;
|
||||||
|
diff --git a/deps/uv/src/unix/core.c b/deps/uv/src/unix/core.c
|
||||||
|
index 7cd3a2a954ff7d70e6ba7a6f7538648841bc54b2..f89b7158218be60ac10e61484a2d5e5e28a3182f 100644
|
||||||
|
--- a/deps/uv/src/unix/core.c
|
||||||
|
+++ b/deps/uv/src/unix/core.c
|
||||||
|
@@ -887,6 +887,9 @@ void uv__io_start(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
|
||||||
|
loop->watchers[w->fd] = w;
|
||||||
|
loop->nfds++;
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+ if (uv__get_internal_fields(loop)->flags & UV_LOOP_INTERRUPT_ON_IO_CHANGE)
|
||||||
|
+ uv__loop_interrupt(loop);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -918,6 +921,9 @@ void uv__io_stop(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
|
||||||
|
}
|
||||||
|
else if (QUEUE_EMPTY(&w->watcher_queue))
|
||||||
|
QUEUE_INSERT_TAIL(&loop->watcher_queue, &w->watcher_queue);
|
||||||
|
+
|
||||||
|
+ if (uv__get_internal_fields(loop)->flags & UV_LOOP_INTERRUPT_ON_IO_CHANGE)
|
||||||
|
+ uv__loop_interrupt(loop);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -934,6 +940,9 @@ void uv__io_close(uv_loop_t* loop, uv__io_t* w) {
|
||||||
|
void uv__io_feed(uv_loop_t* loop, uv__io_t* w) {
|
||||||
|
if (QUEUE_EMPTY(&w->pending_queue))
|
||||||
|
QUEUE_INSERT_TAIL(&loop->pending_queue, &w->pending_queue);
|
||||||
|
+
|
||||||
|
+ if (uv__get_internal_fields(loop)->flags & UV_LOOP_INTERRUPT_ON_IO_CHANGE)
|
||||||
|
+ uv__loop_interrupt(loop);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
diff --git a/deps/uv/src/unix/loop.c b/deps/uv/src/unix/loop.c
|
||||||
|
index a88e71c339351f2ebcdd6c3f933fc3b1122910ed..353143e5ebecae598425dc036f4458bb7c43bb0b 100644
|
||||||
|
--- a/deps/uv/src/unix/loop.c
|
||||||
|
+++ b/deps/uv/src/unix/loop.c
|
||||||
|
@@ -217,6 +217,11 @@ int uv__loop_configure(uv_loop_t* loop, uv_loop_option option, va_list ap) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ if (option == UV_LOOP_INTERRUPT_ON_IO_CHANGE) {
|
||||||
|
+ lfields->flags |= UV_LOOP_INTERRUPT_ON_IO_CHANGE;
|
||||||
|
+ return 0;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
if (option != UV_LOOP_BLOCK_SIGNAL)
|
||||||
|
return UV_ENOSYS;
|
||||||
|
|
||||||
|
@@ -226,3 +231,37 @@ int uv__loop_configure(uv_loop_t* loop, uv_loop_option option, va_list ap) {
|
||||||
|
loop->flags |= UV_LOOP_BLOCK_SIGPROF;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+void uv__loop_interrupt(uv_loop_t* loop) {
|
||||||
|
+ const void* buf;
|
||||||
|
+ ssize_t len;
|
||||||
|
+ int fd;
|
||||||
|
+ int r;
|
||||||
|
+
|
||||||
|
+ buf = "";
|
||||||
|
+ len = 1;
|
||||||
|
+ fd = loop->async_wfd;
|
||||||
|
+
|
||||||
|
+#if defined(__linux__)
|
||||||
|
+ if (fd == -1) {
|
||||||
|
+ static const uint64_t val = 1;
|
||||||
|
+ buf = &val;
|
||||||
|
+ len = sizeof(val);
|
||||||
|
+ fd = loop->async_io_watcher.fd; /* eventfd */
|
||||||
|
+ }
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
+ do
|
||||||
|
+ r = write(fd, buf, len);
|
||||||
|
+ while (r == -1 && errno == EINTR);
|
||||||
|
+
|
||||||
|
+ if (r == len)
|
||||||
|
+ return;
|
||||||
|
+
|
||||||
|
+ if (r == -1)
|
||||||
|
+ if (errno == EAGAIN || errno == EWOULDBLOCK)
|
||||||
|
+ return;
|
||||||
|
+
|
||||||
|
+ abort();
|
||||||
|
+}
|
||||||
|
diff --git a/deps/uv/src/uv-common.h b/deps/uv/src/uv-common.h
|
||||||
|
index 6001b0cf68d0b0268b578218b664a737f43c9521..5d2212571f4bcb648ab332f0c5650d0fdb37c03a 100644
|
||||||
|
--- a/deps/uv/src/uv-common.h
|
||||||
|
+++ b/deps/uv/src/uv-common.h
|
||||||
|
@@ -140,6 +140,8 @@ int uv__loop_configure(uv_loop_t* loop, uv_loop_option option, va_list ap);
|
||||||
|
|
||||||
|
void uv__loop_close(uv_loop_t* loop);
|
||||||
|
|
||||||
|
+void uv__loop_interrupt(uv_loop_t* loop);
|
||||||
|
+
|
||||||
|
int uv__read_start(uv_stream_t* stream,
|
||||||
|
uv_alloc_cb alloc_cb,
|
||||||
|
uv_read_cb read_cb);
|
||||||
|
@@ -268,6 +270,10 @@ void uv__threadpool_cleanup(void);
|
||||||
|
if (((h)->flags & UV_HANDLE_ACTIVE) != 0) break; \
|
||||||
|
(h)->flags |= UV_HANDLE_ACTIVE; \
|
||||||
|
if (((h)->flags & UV_HANDLE_REF) != 0) uv__active_handle_add(h); \
|
||||||
|
+ int loop_flags = uv__get_internal_fields((h)->loop)->flags; \
|
||||||
|
+ if (loop_flags & UV_LOOP_INTERRUPT_ON_IO_CHANGE) { \
|
||||||
|
+ uv__loop_interrupt((h)->loop); \
|
||||||
|
+ } \
|
||||||
|
} \
|
||||||
|
while (0)
|
||||||
|
|
||||||
|
diff --git a/deps/uv/src/win/core.c b/deps/uv/src/win/core.c
|
||||||
|
index e53a0f8e28637a58ceec7852d1a79874fc1a9548..dd4065c1cc68763bfe258492e3119669311394dc 100644
|
||||||
|
--- a/deps/uv/src/win/core.c
|
||||||
|
+++ b/deps/uv/src/win/core.c
|
||||||
|
@@ -381,10 +381,20 @@ int uv__loop_configure(uv_loop_t* loop, uv_loop_option option, va_list ap) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ if (option == UV_LOOP_INTERRUPT_ON_IO_CHANGE) {
|
||||||
|
+ lfields->flags |= UV_LOOP_INTERRUPT_ON_IO_CHANGE;
|
||||||
|
+ return 0;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
return UV_ENOSYS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
+void uv__loop_interrupt(uv_loop_t* loop) {
|
||||||
|
+ PostQueuedCompletionStatus(loop->iocp, 0, 0, NULL);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+
|
||||||
|
int uv_backend_fd(const uv_loop_t* loop) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
diff --git a/deps/uv/test/test-embed.c b/deps/uv/test/test-embed.c
|
||||||
|
index c6ddceb149d9c1d68b0dd17b6dac0d4c3c3e9dbc..f6572c5dc2b6ef39bd11889ad1f7873007a6437d 100644
|
||||||
|
--- a/deps/uv/test/test-embed.c
|
||||||
|
+++ b/deps/uv/test/test-embed.c
|
||||||
|
@@ -25,115 +25,179 @@
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
-#ifndef HAVE_KQUEUE
|
||||||
|
-# if defined(__APPLE__) || \
|
||||||
|
- defined(__DragonFly__) || \
|
||||||
|
- defined(__FreeBSD__) || \
|
||||||
|
- defined(__FreeBSD_kernel__) || \
|
||||||
|
- defined(__OpenBSD__) || \
|
||||||
|
- defined(__NetBSD__)
|
||||||
|
-# define HAVE_KQUEUE 1
|
||||||
|
-# endif
|
||||||
|
-#endif
|
||||||
|
-
|
||||||
|
#ifndef HAVE_EPOLL
|
||||||
|
# if defined(__linux__)
|
||||||
|
# define HAVE_EPOLL 1
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
-#if defined(HAVE_KQUEUE) || defined(HAVE_EPOLL)
|
||||||
|
+#if defined(HAVE_EPOLL)
|
||||||
|
+# include <sys/epoll.h>
|
||||||
|
+#endif
|
||||||
|
|
||||||
|
-#if defined(HAVE_KQUEUE)
|
||||||
|
+#if !defined(_WIN32)
|
||||||
|
# include <sys/types.h>
|
||||||
|
-# include <sys/event.h>
|
||||||
|
# include <sys/time.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
-#if defined(HAVE_EPOLL)
|
||||||
|
-# include <sys/epoll.h>
|
||||||
|
-#endif
|
||||||
|
-
|
||||||
|
+static uv_loop_t main_loop;
|
||||||
|
+static uv_loop_t external_loop;
|
||||||
|
static uv_thread_t embed_thread;
|
||||||
|
static uv_sem_t embed_sem;
|
||||||
|
-static uv_timer_t embed_timer;
|
||||||
|
static uv_async_t embed_async;
|
||||||
|
+static uv_async_t main_async;
|
||||||
|
static volatile int embed_closed;
|
||||||
|
|
||||||
|
-static int embed_timer_called;
|
||||||
|
+static uv_timer_t main_timer;
|
||||||
|
+static int main_timer_called;
|
||||||
|
|
||||||
|
|
||||||
|
-static void embed_thread_runner(void* arg) {
|
||||||
|
+#if defined(_WIN32)
|
||||||
|
+static void embed_thread_poll_win(HANDLE iocp, int timeout) {
|
||||||
|
+ DWORD bytes;
|
||||||
|
+ ULONG_PTR key;
|
||||||
|
+ OVERLAPPED* overlapped;
|
||||||
|
+
|
||||||
|
+ GetQueuedCompletionStatus(iocp,
|
||||||
|
+ &bytes,
|
||||||
|
+ &key,
|
||||||
|
+ &overlapped,
|
||||||
|
+ timeout >= 0 ? timeout : INFINITE);
|
||||||
|
+
|
||||||
|
+ /* Give the event back so the loop can deal with it. */
|
||||||
|
+ if (overlapped != NULL)
|
||||||
|
+ PostQueuedCompletionStatus(iocp,
|
||||||
|
+ bytes,
|
||||||
|
+ key,
|
||||||
|
+ overlapped);
|
||||||
|
+}
|
||||||
|
+#else
|
||||||
|
+static void embed_thread_poll_unix(int fd, int timeout) {
|
||||||
|
int r;
|
||||||
|
- int fd;
|
||||||
|
+ do {
|
||||||
|
+#if defined(HAVE_EPOLL)
|
||||||
|
+ struct epoll_event ev;
|
||||||
|
+ r = epoll_wait(fd, &ev, 1, timeout);
|
||||||
|
+#else
|
||||||
|
+ struct timeval tv;
|
||||||
|
+ if (timeout >= 0) {
|
||||||
|
+ tv.tv_sec = timeout / 1000;
|
||||||
|
+ tv.tv_usec = (timeout % 1000) * 1000;
|
||||||
|
+ }
|
||||||
|
+ fd_set readset;
|
||||||
|
+ FD_ZERO(&readset);
|
||||||
|
+ FD_SET(fd, &readset);
|
||||||
|
+ r = select(fd + 1, &readset, NULL, NULL, timeout >= 0 ? &tv : NULL);
|
||||||
|
+#endif
|
||||||
|
+ } while (r == -1 && errno == EINTR);
|
||||||
|
+}
|
||||||
|
+#endif /* !_WIN32 */
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+static void embed_thread_runner(void* arg) {
|
||||||
|
int timeout;
|
||||||
|
|
||||||
|
- while (!embed_closed) {
|
||||||
|
- fd = uv_backend_fd(uv_default_loop());
|
||||||
|
- timeout = uv_backend_timeout(uv_default_loop());
|
||||||
|
-
|
||||||
|
- do {
|
||||||
|
-#if defined(HAVE_KQUEUE)
|
||||||
|
- struct timespec ts;
|
||||||
|
- ts.tv_sec = timeout / 1000;
|
||||||
|
- ts.tv_nsec = (timeout % 1000) * 1000000;
|
||||||
|
- r = kevent(fd, NULL, 0, NULL, 0, &ts);
|
||||||
|
-#elif defined(HAVE_EPOLL)
|
||||||
|
- {
|
||||||
|
- struct epoll_event ev;
|
||||||
|
- r = epoll_wait(fd, &ev, 1, timeout);
|
||||||
|
- }
|
||||||
|
+ do {
|
||||||
|
+ timeout = uv_backend_timeout(&main_loop);
|
||||||
|
+
|
||||||
|
+#if defined(_WIN32)
|
||||||
|
+ embed_thread_poll_win(main_loop.iocp, timeout);
|
||||||
|
+#else
|
||||||
|
+ embed_thread_poll_unix(uv_backend_fd(&main_loop), timeout);
|
||||||
|
#endif
|
||||||
|
- } while (r == -1 && errno == EINTR);
|
||||||
|
+
|
||||||
|
uv_async_send(&embed_async);
|
||||||
|
+
|
||||||
|
uv_sem_wait(&embed_sem);
|
||||||
|
- }
|
||||||
|
+ } while (!embed_closed);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void embed_cb(uv_async_t* async) {
|
||||||
|
- uv_run(uv_default_loop(), UV_RUN_ONCE);
|
||||||
|
+ /* Run tasks in main loop */
|
||||||
|
+ uv_run(&main_loop, UV_RUN_NOWAIT);
|
||||||
|
|
||||||
|
+ /* Tell embed thread to continue polling */
|
||||||
|
uv_sem_post(&embed_sem);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
-static void embed_timer_cb(uv_timer_t* timer) {
|
||||||
|
- embed_timer_called++;
|
||||||
|
+static void main_timer_cb(uv_timer_t* timer) {
|
||||||
|
+ main_timer_called++;
|
||||||
|
embed_closed = 1;
|
||||||
|
|
||||||
|
uv_close((uv_handle_t*) &embed_async, NULL);
|
||||||
|
+ uv_close((uv_handle_t*) &main_async, NULL);
|
||||||
|
}
|
||||||
|
-#endif
|
||||||
|
|
||||||
|
|
||||||
|
-TEST_IMPL(embed) {
|
||||||
|
-#if defined(HAVE_KQUEUE) || defined(HAVE_EPOLL)
|
||||||
|
- uv_loop_t external;
|
||||||
|
-
|
||||||
|
- ASSERT(0 == uv_loop_init(&external));
|
||||||
|
+static void init_loops(void) {
|
||||||
|
+ ASSERT_EQ(0, uv_loop_init(&main_loop));
|
||||||
|
+ ASSERT_EQ(0, uv_loop_init(&external_loop));
|
||||||
|
|
||||||
|
- embed_timer_called = 0;
|
||||||
|
+ main_timer_called = 0;
|
||||||
|
embed_closed = 0;
|
||||||
|
|
||||||
|
- uv_async_init(&external, &embed_async, embed_cb);
|
||||||
|
+ uv_async_init(&external_loop, &embed_async, embed_cb);
|
||||||
|
|
||||||
|
- /* Start timer in default loop */
|
||||||
|
- uv_timer_init(uv_default_loop(), &embed_timer);
|
||||||
|
- uv_timer_start(&embed_timer, embed_timer_cb, 250, 0);
|
||||||
|
+ /* Create a dummy async for main loop otherwise backend timeout will
|
||||||
|
+ always be 0 */
|
||||||
|
+ uv_async_init(&main_loop, &main_async, embed_cb);
|
||||||
|
|
||||||
|
- /* Start worker that will interrupt external loop */
|
||||||
|
+ /* Start worker that will poll main loop and interrupt external loop */
|
||||||
|
uv_sem_init(&embed_sem, 0);
|
||||||
|
uv_thread_create(&embed_thread, embed_thread_runner, NULL);
|
||||||
|
+}
|
||||||
|
|
||||||
|
- /* But run external loop */
|
||||||
|
- uv_run(&external, UV_RUN_DEFAULT);
|
||||||
|
+
|
||||||
|
+static void run_loop(void) {
|
||||||
|
+ /* Run external loop */
|
||||||
|
+ uv_run(&external_loop, UV_RUN_DEFAULT);
|
||||||
|
|
||||||
|
uv_thread_join(&embed_thread);
|
||||||
|
- uv_loop_close(&external);
|
||||||
|
+ uv_sem_destroy(&embed_sem);
|
||||||
|
+ uv_loop_close(&external_loop);
|
||||||
|
+ uv_loop_close(&main_loop);
|
||||||
|
+}
|
||||||
|
|
||||||
|
- ASSERT(embed_timer_called == 1);
|
||||||
|
-#endif
|
||||||
|
+
|
||||||
|
+TEST_IMPL(embed) {
|
||||||
|
+ init_loops();
|
||||||
|
+
|
||||||
|
+ /* Start timer in main loop */
|
||||||
|
+ uv_timer_init(&main_loop, &main_timer);
|
||||||
|
+ uv_timer_start(&main_timer, main_timer_cb, 250, 0);
|
||||||
|
+
|
||||||
|
+ run_loop();
|
||||||
|
+ ASSERT_EQ(main_timer_called, 1);
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+static uv_timer_t external_timer;
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+static void external_timer_cb(uv_timer_t* timer) {
|
||||||
|
+ /* Start timer in main loop */
|
||||||
|
+ uv_timer_init(&main_loop, &main_timer);
|
||||||
|
+ uv_timer_start(&main_timer, main_timer_cb, 250, 0);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+TEST_IMPL(embed_with_external_timer) {
|
||||||
|
+ init_loops();
|
||||||
|
+
|
||||||
|
+ /* Interrupt embed polling when a handle is started */
|
||||||
|
+ ASSERT_EQ(0, uv_loop_configure(&main_loop, UV_LOOP_INTERRUPT_ON_IO_CHANGE));
|
||||||
|
+
|
||||||
|
+ /* Start timer in external loop, whose callback will not interrupt the
|
||||||
|
+ polling in embed thread */
|
||||||
|
+ uv_timer_init(&external_loop, &external_timer);
|
||||||
|
+ uv_timer_start(&external_timer, external_timer_cb, 100, 0);
|
||||||
|
+
|
||||||
|
+ run_loop();
|
||||||
|
+ ASSERT_EQ(main_timer_called, 1);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
diff --git a/deps/uv/test/test-list.h b/deps/uv/test/test-list.h
|
||||||
|
index a43edf1a4a9b0932ec73b8edaca0f676ecf3ccfa..199402e31406cf8ba360d54769461bb5285011ee 100644
|
||||||
|
--- a/deps/uv/test/test-list.h
|
||||||
|
+++ b/deps/uv/test/test-list.h
|
||||||
|
@@ -263,6 +263,7 @@ TEST_DECLARE (process_priority)
|
||||||
|
TEST_DECLARE (has_ref)
|
||||||
|
TEST_DECLARE (active)
|
||||||
|
TEST_DECLARE (embed)
|
||||||
|
+TEST_DECLARE (embed_with_external_timer)
|
||||||
|
TEST_DECLARE (async)
|
||||||
|
TEST_DECLARE (async_null_cb)
|
||||||
|
TEST_DECLARE (eintr_handling)
|
||||||
|
@@ -860,6 +861,7 @@ TASK_LIST_START
|
||||||
|
TEST_ENTRY (active)
|
||||||
|
|
||||||
|
TEST_ENTRY (embed)
|
||||||
|
+ TEST_ENTRY (embed_with_external_timer)
|
||||||
|
|
||||||
|
TEST_ENTRY (async)
|
||||||
|
TEST_ENTRY (async_null_cb)
|
|
@ -1,59 +0,0 @@
|
||||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Shelley Vohr <shelley.vohr@gmail.com>
|
|
||||||
Date: Mon, 30 Jul 2018 10:34:54 -0700
|
|
||||||
Subject: feat: add uv_loop watcher_queue code
|
|
||||||
|
|
||||||
Electron's Node Integration works by listening to Node's backend file descriptor in a separate thread; when an event is ready the backend file descriptor will trigger a new event for it, and the main thread will then iterate the libuv loop. For certain operations (ex. adding a timeout task) the backend file descriptor isn't informed, & as a result the main thread doesn't know it needs to iterate the libuv loop so the timeout task will never execute until something else trigger a new event. This commit should be removed when https://github.com/libuv/libuv/pull/1921 is merged
|
|
||||||
|
|
||||||
diff --git a/deps/uv/include/uv.h b/deps/uv/include/uv.h
|
|
||||||
index 606083c87de5790d7e66fc34aeaae9a58acb8ef4..ca9568c58b1ccd554318f5deb27d2b4e80f08a28 100644
|
|
||||||
--- a/deps/uv/include/uv.h
|
|
||||||
+++ b/deps/uv/include/uv.h
|
|
||||||
@@ -1805,6 +1805,8 @@ union uv_any_req {
|
|
||||||
struct uv_loop_s {
|
|
||||||
/* User data - use this for whatever. */
|
|
||||||
void* data;
|
|
||||||
+ /* Callback when loop's watcher queue updates. */
|
|
||||||
+ void (*on_watcher_queue_updated)(uv_loop_t*);
|
|
||||||
/* Loop reference counting. */
|
|
||||||
unsigned int active_handles;
|
|
||||||
void* handle_queue[2];
|
|
||||||
diff --git a/deps/uv/src/unix/core.c b/deps/uv/src/unix/core.c
|
|
||||||
index 71e9c525c4a77b8b5322e8516c58329100a8d951..a6425294086ff2f1435fdd6866380d3aaaf68200 100644
|
|
||||||
--- a/deps/uv/src/unix/core.c
|
|
||||||
+++ b/deps/uv/src/unix/core.c
|
|
||||||
@@ -906,8 +906,11 @@ void uv__io_start(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
|
|
||||||
return;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
- if (QUEUE_EMPTY(&w->watcher_queue))
|
|
||||||
+ if (QUEUE_EMPTY(&w->watcher_queue)) {
|
|
||||||
QUEUE_INSERT_TAIL(&loop->watcher_queue, &w->watcher_queue);
|
|
||||||
+ if (loop->on_watcher_queue_updated)
|
|
||||||
+ loop->on_watcher_queue_updated(loop);
|
|
||||||
+ }
|
|
||||||
|
|
||||||
if (loop->watchers[w->fd] == NULL) {
|
|
||||||
loop->watchers[w->fd] = w;
|
|
||||||
@@ -942,8 +945,11 @@ void uv__io_stop(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
|
|
||||||
loop->nfds--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
- else if (QUEUE_EMPTY(&w->watcher_queue))
|
|
||||||
+ else if (QUEUE_EMPTY(&w->watcher_queue)) {
|
|
||||||
QUEUE_INSERT_TAIL(&loop->watcher_queue, &w->watcher_queue);
|
|
||||||
+ if (loop->on_watcher_queue_updated)
|
|
||||||
+ loop->on_watcher_queue_updated(loop);
|
|
||||||
+ }
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@@ -960,6 +966,8 @@ void uv__io_close(uv_loop_t* loop, uv__io_t* w) {
|
|
||||||
void uv__io_feed(uv_loop_t* loop, uv__io_t* w) {
|
|
||||||
if (QUEUE_EMPTY(&w->pending_queue))
|
|
||||||
QUEUE_INSERT_TAIL(&loop->pending_queue, &w->pending_queue);
|
|
||||||
+ if (loop->on_watcher_queue_updated)
|
|
||||||
+ loop->on_watcher_queue_updated(loop);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ Now that uv__cloexec_fcntl() is simplified
|
||||||
maintaining duplicate code paths for the same thing.
|
maintaining duplicate code paths for the same thing.
|
||||||
|
|
||||||
diff --git a/deps/uv/src/unix/core.c b/deps/uv/src/unix/core.c
|
diff --git a/deps/uv/src/unix/core.c b/deps/uv/src/unix/core.c
|
||||||
index 6cd519ad5b3e7af8f5c71b18a59b88458a233f15..8c30802ad15316a8ec20ecedfb5123174d74276b 100644
|
index a87b96cfc1dfdc88fa712a4fa991320ff28f2dcd..7cd3a2a954ff7d70e6ba7a6f7538648841bc54b2 100644
|
||||||
--- a/deps/uv/src/unix/core.c
|
--- a/deps/uv/src/unix/core.c
|
||||||
+++ b/deps/uv/src/unix/core.c
|
+++ b/deps/uv/src/unix/core.c
|
||||||
@@ -597,20 +597,6 @@ int uv__nonblock_ioctl(int fd, int set) {
|
@@ -597,20 +597,6 @@ int uv__nonblock_ioctl(int fd, int set) {
|
||||||
|
|
|
@ -7,7 +7,7 @@ FD_CLOEXEC is the only defined flag for fcntl(F_SETFD) so don't bother
|
||||||
getting the status of that flag first with fcntl(F_GETFD), just set it.
|
getting the status of that flag first with fcntl(F_GETFD), just set it.
|
||||||
|
|
||||||
diff --git a/deps/uv/src/unix/core.c b/deps/uv/src/unix/core.c
|
diff --git a/deps/uv/src/unix/core.c b/deps/uv/src/unix/core.c
|
||||||
index a6425294086ff2f1435fdd6866380d3aaaf68200..6cd519ad5b3e7af8f5c71b18a59b88458a233f15 100644
|
index 71e9c525c4a77b8b5322e8516c58329100a8d951..a87b96cfc1dfdc88fa712a4fa991320ff28f2dcd 100644
|
||||||
--- a/deps/uv/src/unix/core.c
|
--- a/deps/uv/src/unix/core.c
|
||||||
+++ b/deps/uv/src/unix/core.c
|
+++ b/deps/uv/src/unix/core.c
|
||||||
@@ -649,21 +649,9 @@ int uv__cloexec_fcntl(int fd, int set) {
|
@@ -649,21 +649,9 @@ int uv__cloexec_fcntl(int fd, int set) {
|
||||||
|
|
|
@ -322,6 +322,9 @@ NodeBindings::NodeBindings(BrowserEnvironment browser_env)
|
||||||
} else {
|
} else {
|
||||||
uv_loop_ = uv_default_loop();
|
uv_loop_ = uv_default_loop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Interrupt embed polling when a handle is started.
|
||||||
|
uv_loop_configure(uv_loop_, UV_LOOP_INTERRUPT_ON_IO_CHANGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
NodeBindings::~NodeBindings() {
|
NodeBindings::~NodeBindings() {
|
||||||
|
|
|
@ -38,22 +38,9 @@ void NodeBindingsLinux::RunMessageLoop() {
|
||||||
|
|
||||||
handle_ = handle;
|
handle_ = handle;
|
||||||
|
|
||||||
// Get notified when libuv's watcher queue changes.
|
|
||||||
uv_loop_->data = this;
|
|
||||||
uv_loop_->on_watcher_queue_updated = OnWatcherQueueChanged;
|
|
||||||
|
|
||||||
NodeBindings::RunMessageLoop();
|
NodeBindings::RunMessageLoop();
|
||||||
}
|
}
|
||||||
|
|
||||||
// static
|
|
||||||
void NodeBindingsLinux::OnWatcherQueueChanged(uv_loop_t* loop) {
|
|
||||||
NodeBindingsLinux* self = static_cast<NodeBindingsLinux*>(loop->data);
|
|
||||||
|
|
||||||
// We need to break the io polling in the epoll thread when loop's watcher
|
|
||||||
// queue changes, otherwise new events cannot be notified.
|
|
||||||
self->WakeupEmbedThread();
|
|
||||||
}
|
|
||||||
|
|
||||||
void NodeBindingsLinux::PollEvents() {
|
void NodeBindingsLinux::PollEvents() {
|
||||||
int timeout = uv_backend_timeout(uv_loop_);
|
int timeout = uv_backend_timeout(uv_loop_);
|
||||||
|
|
||||||
|
|
|
@ -19,9 +19,6 @@ class NodeBindingsLinux : public NodeBindings {
|
||||||
void RunMessageLoop() override;
|
void RunMessageLoop() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Called when uv's watcher queue changes.
|
|
||||||
static void OnWatcherQueueChanged(uv_loop_t* loop);
|
|
||||||
|
|
||||||
void PollEvents() override;
|
void PollEvents() override;
|
||||||
|
|
||||||
// Epoll to poll for uv's backend fd.
|
// Epoll to poll for uv's backend fd.
|
||||||
|
|
|
@ -38,22 +38,9 @@ void NodeBindingsMac::RunMessageLoop() {
|
||||||
|
|
||||||
handle_ = handle;
|
handle_ = handle;
|
||||||
|
|
||||||
// Get notified when libuv's watcher queue changes.
|
|
||||||
uv_loop_->data = this;
|
|
||||||
uv_loop_->on_watcher_queue_updated = OnWatcherQueueChanged;
|
|
||||||
|
|
||||||
NodeBindings::RunMessageLoop();
|
NodeBindings::RunMessageLoop();
|
||||||
}
|
}
|
||||||
|
|
||||||
// static
|
|
||||||
void NodeBindingsMac::OnWatcherQueueChanged(uv_loop_t* loop) {
|
|
||||||
NodeBindingsMac* self = static_cast<NodeBindingsMac*>(loop->data);
|
|
||||||
|
|
||||||
// We need to break the io polling in the kqueue thread when loop's watcher
|
|
||||||
// queue changes, otherwise new events cannot be notified.
|
|
||||||
self->WakeupEmbedThread();
|
|
||||||
}
|
|
||||||
|
|
||||||
void NodeBindingsMac::PollEvents() {
|
void NodeBindingsMac::PollEvents() {
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
int timeout = uv_backend_timeout(uv_loop_);
|
int timeout = uv_backend_timeout(uv_loop_);
|
||||||
|
|
|
@ -19,9 +19,6 @@ class NodeBindingsMac : public NodeBindings {
|
||||||
void RunMessageLoop() override;
|
void RunMessageLoop() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Called when uv's watcher queue changes.
|
|
||||||
static void OnWatcherQueueChanged(uv_loop_t* loop);
|
|
||||||
|
|
||||||
void PollEvents() override;
|
void PollEvents() override;
|
||||||
|
|
||||||
// uv's backend fd.
|
// uv's backend fd.
|
||||||
|
|
Loading…
Reference in a new issue