refactor(napi): use get_uv_event_loop instead of uv_default_loop

Using the uv_loop_s from napi_env is safer as it's possible that
there are multiple Workers, and therefore multiple uv_loop_s.
This commit is contained in:
Ouyang Yadong 2020-08-18 13:55:35 +08:00
parent 0bfacc536a
commit 00454eb577
3 changed files with 55 additions and 2 deletions

View file

@ -533,6 +533,17 @@ impl Env {
.map_err(|e| Error::new(Status::InvalidArg, format!("{}", e)))
}
#[cfg(napi2)]
#[inline]
pub fn get_uv_event_loop(&self) -> Result<*mut sys::uv_loop_s> {
let mut uv_loop: *mut sys::uv_loop_s = ptr::null_mut();
Ok(unsafe {
let status = sys::napi_get_uv_event_loop(self.0, &mut uv_loop);
check_status(status)?;
uv_loop
})
}
#[cfg(all(feature = "libuv", napi4))]
#[inline]
pub fn execute<
@ -553,7 +564,7 @@ impl Env {
check_status(status)?;
}
let event_loop = unsafe { sys::uv_default_loop() };
let event_loop = self.get_uv_event_loop()?;
let future_promise = promise::FuturePromise::create(self.0, raw_deferred, Box::from(resolver))?;
let future_to_execute = promise::resolve_from_future(future_promise.start()?, deferred);
uv::execute(event_loop, Box::pin(future_to_execute))?;

View file

@ -1,10 +1,18 @@
const test = require('ava')
const { join } = require('path')
const { join, resolve } = require('path')
const { readFileSync } = require('fs')
const bindings = require('../../index.node')
const napiVersion = require('../napi-version')
let threadMod
try {
threadMod = require('worker_threads')
} catch (err) {
//
}
const filepath = join(__dirname, './example.txt')
test('should execute future on libuv thread pool', async (t) => {
@ -16,3 +24,21 @@ test('should execute future on libuv thread pool', async (t) => {
t.true(Buffer.isBuffer(fileContent))
t.deepEqual(readFileSync(filepath), fileContent)
})
test('should execute future on libuv thread pool of "Worker"', async (t) => {
// Test in threads if current Node.js supports "worker_threads".`
if (!threadMod || napiVersion < 4) {
return
}
const { Worker } = threadMod
const script = resolve(__dirname, './uv_worker.js')
const worker = new Worker(script)
const success = await new Promise((resolve) => {
worker.on('message', (success) => {
resolve(success)
})
})
t.is(success, true)
})

View file

@ -0,0 +1,16 @@
const { isMainThread, parentPort } = require('worker_threads')
const { join } = require('path')
const { readFileSync } = require('fs')
const bindings = require('../../index.node')
const filepath = join(__dirname, './example.txt')
if (!isMainThread) {
;(async () => {
const fileContent = await bindings.uvReadFile(filepath)
const success =
Buffer.isBuffer(fileContent) &&
readFileSync(filepath).toString('utf8') === fileContent.toString('utf8')
parentPort.postMessage(success)
})()
}