diff --git a/include/uv/unix.h b/include/uv/unix.h index ea37d78768654eef98e10982a6b6ddce934bbbbf..ab694b5f18092acb4d4451ad3a86fdb69b5fb916 100644 --- a/include/uv/unix.h +++ b/include/uv/unix.h @@ -219,6 +219,7 @@ typedef struct { } uv_lib_t; #define UV_LOOP_PRIVATE_FIELDS \ + unsigned int magic; \ unsigned long flags; \ int backend_fd; \ void* pending_queue[2]; \ diff --git a/include/uv/win.h b/include/uv/win.h index 62be4b04ea81286bcff9a2f1dc7fee7f0df5c0bc..3f628930e0b51ef90a279e0aee1bf2c0702ddb78 100644 --- a/include/uv/win.h +++ b/include/uv/win.h @@ -323,6 +323,7 @@ typedef struct { } uv_lib_t; #define UV_LOOP_PRIVATE_FIELDS \ + unsigned int magic; \ /* The loop's I/O completion port */ \ HANDLE iocp; \ /* The current time according to the event loop. in msecs. */ \ diff --git a/src/threadpool.c b/src/threadpool.c index 154c953df7f564274d021b292a72e333168a49f4..45dc00fe0bc02451cc3c0649785a21e23060ddb0 100644 --- a/src/threadpool.c +++ b/src/threadpool.c @@ -23,6 +23,8 @@ #if !defined(_WIN32) # include "unix/internal.h" +#else +# include "win/internal.h" #endif #include @@ -30,6 +32,9 @@ #include #include "ffrt_inner.h" #endif +#ifdef _GNU_SOURCE +#include +#endif #define MAX_THREADPOOL_SIZE 1024 @@ -374,20 +379,52 @@ static void uv__queue_done(struct uv__work* w, int err) { #ifdef USE_FFRT +#define UV_LOG(level, fmt, ...) do { \ +if (HiLogPrint) \ + HiLogPrint(3, level, 0xD003900, "UV", fmt, ##__VA_ARGS__); \ +} while (0) +#define UV_LOGI(fmt, ...) UV_LOG(4, fmt, ##__VA_ARGS__) +#define UV_LOGE(fmt, ...) UV_LOG(6, fmt, ##__VA_ARGS__) + + +static int (*HiLogPrint)(int, int, unsigned int, const char*, const char*, ...); + +static uv_once_t g_closed_uv_loop_rwlock_once = UV_ONCE_INIT; +static uv_rwlock_t g_closed_uv_loop_rwlock; + + +static void init_closed_uv_loop_rwlock_once(void) { + uv_rwlock_init(&g_closed_uv_loop_rwlock); +#ifdef _GNU_SOURCE + HiLogPrint = (int (*)(int, int, unsigned int, const char*, const char*, ...))dlsym(RTLD_DEFAULT, "HiLogPrint"); +#endif +} + void uv__ffrt_work(ffrt_executor_task_t* data, ffrt_qos_t qos) { struct uv__work* w = (struct uv__work *)data; w->work(w); uv__loop_internal_fields_t* lfields = uv__get_internal_fields(w->loop); - if (&lfields->wq_sub[qos][0] == NULL || &lfields->wq_sub[qos][1] == NULL) + uv_once(&g_closed_uv_loop_rwlock_once, init_closed_uv_loop_rwlock_once); + uv_rwlock_rdlock(&g_closed_uv_loop_rwlock); + if (w->loop->magic != UV_LOOP_MAGIC + || !lfields + || qos >= ARRAY_SIZE(lfields->wq_sub) + || !lfields->wq_sub[qos][0] + || !lfields->wq_sub[qos][1]) { + uv_rwlock_rdunlock(&g_closed_uv_loop_rwlock); + uv_work_t* req = container_of(w, uv_work_t, work_req); + UV_LOGE("uv_loop(%p:%#x) in task(%p:%p) is invalid", w->loop, w->loop->magic, req->work_cb, req->after_work_cb); return; + } uv_mutex_lock(&w->loop->wq_mutex); w->work = NULL; /* Signal uv_cancel() that the work req is done executing. */ QUEUE_INSERT_TAIL(&(lfields->wq_sub[qos]), &w->wq); uv_async_send(&w->loop->wq_async); uv_mutex_unlock(&w->loop->wq_mutex); + uv_rwlock_rdunlock(&g_closed_uv_loop_rwlock); } static void init_once(void) diff --git a/src/unix/internal.h b/src/unix/internal.h index f418572dea6a5c16e7ae539f507d84160ac28198..c175fa97a3af8e67a586677fa3f9ed65334ecb82 100644 --- a/src/unix/internal.h +++ b/src/unix/internal.h @@ -33,6 +33,8 @@ #include #include +#define UV_LOOP_MAGIC 0x100B100BU + #if defined(__STRICT_ANSI__) # define inline __inline #endif diff --git a/src/win/internal.h b/src/win/internal.h index 17e399be5c7a75216dd22f702b3014e019ae650a..6379582263121679ee81b72cb519f15681cb9bfc 100644 --- a/src/win/internal.h +++ b/src/win/internal.h @@ -29,6 +29,8 @@ #include "winapi.h" #include "winsock.h" +#define UV_LOOP_MAGIC 0x700B700BU + #ifdef _MSC_VER # define INLINE __inline # define UV_THREAD_LOCAL __declspec( thread )