From 3eb34068a2f8d97a269074b66b1afe74297d4e9e Mon Sep 17 00:00:00 2001 From: Stephen Belanger Date: Tue, 25 Feb 2020 22:12:51 +0800 Subject: [PATCH] async_hooks: prevent sync methods of async storage exiting outer context MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR-URL: https://github.com/nodejs/node/pull/31950 Reviewed-By: Vladimir de Turckheim Reviewed-By: Gerhard Stöbich --- lib/async_hooks.js | 20 ++++++++----------- .../test-async-local-storage-run-resource.js | 17 ++++++++++++++++ 2 files changed, 25 insertions(+), 12 deletions(-) create mode 100644 test/async-hooks/test-async-local-storage-run-resource.js diff --git a/lib/async_hooks.js b/lib/async_hooks.js index cb017222a9bce2..dadde6a0f2e7ad 100644 --- a/lib/async_hooks.js +++ b/lib/async_hooks.js @@ -257,14 +257,11 @@ class AsyncLocalStorage { } runSyncAndReturn(store, callback, ...args) { - const resource = executionAsyncResource(); - const outerStore = resource[this.kResourceStore]; - this.enterWith(store); - try { + const resource = new AsyncResource('AsyncLocalStorage'); + return resource.runInAsyncScope(() => { + this.enterWith(store); return callback(...args); - } finally { - resource[this.kResourceStore] = outerStore; - } + }); } exitSyncAndReturn(callback, ...args) { @@ -287,11 +284,10 @@ class AsyncLocalStorage { } run(store, callback, ...args) { - const resource = executionAsyncResource(); - const outerStore = resource[this.kResourceStore]; - this.enterWith(store); - process.nextTick(callback, ...args); - resource[this.kResourceStore] = outerStore; + process.nextTick(() => { + this.enterWith(store); + return callback(...args); + }); } exit(callback, ...args) { diff --git a/test/async-hooks/test-async-local-storage-run-resource.js b/test/async-hooks/test-async-local-storage-run-resource.js new file mode 100644 index 00000000000000..9a7479f699246c --- /dev/null +++ b/test/async-hooks/test-async-local-storage-run-resource.js @@ -0,0 +1,17 @@ +'use strict'; +require('../common'); +const assert = require('assert'); +const { + AsyncLocalStorage, + executionAsyncResource +} = require('async_hooks'); + +const asyncLocalStorage = new AsyncLocalStorage(); + +const outerResource = executionAsyncResource(); + +asyncLocalStorage.run(new Map(), () => { + assert.notStrictEqual(executionAsyncResource(), outerResource); +}); + +assert.strictEqual(executionAsyncResource(), outerResource);