| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 8516da1 commit 8a3ffca
4 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -176,7 +176,7 @@ void AsyncWrap::EmitAfter(Environment* env, double async_id) { | |||
| 176 | 176 | class PromiseWrap : public AsyncWrap { | |
| 177 | 177 | public: | |
| 178 | 178 | PromiseWrap(Environment* env, Local<Object> object, bool silent) | |
| 179 | - : AsyncWrap(env, object, PROVIDER_PROMISE, -1, silent) { | ||
| 179 | + : AsyncWrap(env, object, PROVIDER_PROMISE, kInvalidAsyncId, silent) { | ||
| 180 | 180 | MakeWeak(); | |
| 181 | 181 | } | |
| 182 | 182 | ||
@@ -382,7 +382,7 @@ static void RegisterDestroyHook(const FunctionCallbackInfo<Value>& args) { | |||
| 382 | 382 | ||
| 383 | 383 | void AsyncWrap::GetAsyncId(const FunctionCallbackInfo<Value>& args) { | |
| 384 | 384 | AsyncWrap* wrap; | |
| 385 | - args.GetReturnValue().Set(-1); | ||
| 385 | + args.GetReturnValue().Set(kInvalidAsyncId); | ||
| 386 | 386 | ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder()); | |
| 387 | 387 | args.GetReturnValue().Set(wrap->get_async_id()); | |
| 388 | 388 | } | |
@@ -409,10 +409,15 @@ void AsyncWrap::AsyncReset(const FunctionCallbackInfo<Value>& args) { | |||
| 409 | 409 | AsyncWrap* wrap; | |
| 410 | 410 | ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder()); | |
| 411 | 411 | double execution_async_id = | |
| 412 | - args[0]->IsNumber() ? args[0].As<Number>()->Value() : -1; | ||
| 412 | + args[0]->IsNumber() ? args[0].As<Number>()->Value() : kInvalidAsyncId; | ||
| 413 | 413 | wrap->AsyncReset(execution_async_id); | |
| 414 | 414 | } | |
| 415 | 415 | ||
| 416 | + void AsyncWrap::EmitDestroy() { | ||
| 417 | + AsyncWrap::EmitDestroy(env(), async_id_); | ||
| 418 | + // Ensure no double destroy is emitted via AsyncReset(). | ||
| 419 | + async_id_ = kInvalidAsyncId; | ||
| 420 | + } | ||
| 416 | 421 | ||
| 417 | 422 | void AsyncWrap::QueueDestroyAsyncId(const FunctionCallbackInfo<Value>& args) { | |
| 418 | 423 | CHECK(args[0]->IsNumber()); | |
@@ -474,7 +479,7 @@ void AsyncWrap::Initialize(Local<Object> target, | |||
| 474 | 479 | // kDefaultTriggerAsyncId: Write the id of the resource responsible for a | |
| 475 | 480 | // handle's creation just before calling the new handle's constructor. | |
| 476 | 481 | // After the new handle is constructed kDefaultTriggerAsyncId is set back | |
| 477 | - // to -1. | ||
| 482 | + // to kInvalidAsyncId. | ||
| 478 | 483 | FORCE_SET_TARGET_FIELD(target, | |
| 479 | 484 | "async_id_fields", | |
| 480 | 485 | env->async_hooks()->async_id_fields().GetJSArray()); | |
@@ -558,15 +563,15 @@ AsyncWrap::AsyncWrap(Environment* env, | |||
| 558 | 563 | CHECK_NE(provider, PROVIDER_NONE); | |
| 559 | 564 | CHECK_GE(object->InternalFieldCount(), 1); | |
| 560 | 565 | ||
| 561 | - async_id_ = -1; | ||
| 566 | + async_id_ = kInvalidAsyncId; | ||
| 562 | 567 | // Use AsyncReset() call to execute the init() callbacks. | |
| 563 | 568 | AsyncReset(execution_async_id, silent); | |
| 564 | 569 | } | |
| 565 | 570 | ||
| 566 | 571 | ||
| 567 | 572 | AsyncWrap::~AsyncWrap() { | |
| 568 | 573 | EmitTraceEventDestroy(); | |
| 569 | - EmitDestroy(env(), get_async_id()); | ||
| 574 | + EmitDestroy(); | ||
| 570 | 575 | } | |
| 571 | 576 | ||
| 572 | 577 | void AsyncWrap::EmitTraceEventDestroy() { | |
@@ -602,16 +607,16 @@ void AsyncWrap::EmitDestroy(Environment* env, double async_id) { | |||
| 602 | 607 | // and reused over their lifetime. This way a new uid can be assigned when | |
| 603 | 608 | // the resource is pulled out of the pool and put back into use. | |
| 604 | 609 | void AsyncWrap::AsyncReset(double execution_async_id, bool silent) { | |
| 605 | - if (async_id_ != -1) { | ||
| 610 | + if (async_id_ != kInvalidAsyncId) { | ||
| 606 | 611 | // This instance was in use before, we have already emitted an init with | |
| 607 | 612 | // its previous async_id and need to emit a matching destroy for that | |
| 608 | 613 | // before generating a new async_id. | |
| 609 | - EmitDestroy(env(), async_id_); | ||
| 614 | + EmitDestroy(); | ||
| 610 | 615 | } | |
| 611 | 616 | ||
| 612 | 617 | // Now we can assign a new async_id_ to this instance. | |
| 613 | - async_id_ = | ||
| 614 | - execution_async_id == -1 ? env()->new_async_id() : execution_async_id; | ||
| 618 | + async_id_ = execution_async_id == kInvalidAsyncId ? env()->new_async_id() | ||
| 619 | + : execution_async_id; | ||
| 615 | 620 | trigger_async_id_ = env()->get_default_trigger_async_id(); | |
| 616 | 621 | ||
| 617 | 622 | switch (provider_type()) { | |
@@ -693,7 +698,7 @@ async_id AsyncHooksGetExecutionAsyncId(Isolate* isolate) { | |||
| 693 | 698 | // Environment::GetCurrent() allocates a Local<> handle. | |
| 694 | 699 | HandleScope handle_scope(isolate); | |
| 695 | 700 | Environment* env = Environment::GetCurrent(isolate); | |
| 696 | - if (env == nullptr) return -1; | ||
| 701 | + if (env == nullptr) return AsyncWrap::kInvalidAsyncId; | ||
| 697 | 702 | return env->execution_async_id(); | |
| 698 | 703 | } | |
| 699 | 704 | ||
@@ -702,7 +707,7 @@ async_id AsyncHooksGetTriggerAsyncId(Isolate* isolate) { | |||
| 702 | 707 | // Environment::GetCurrent() allocates a Local<> handle. | |
| 703 | 708 | HandleScope handle_scope(isolate); | |
| 704 | 709 | Environment* env = Environment::GetCurrent(isolate); | |
| 705 | - if (env == nullptr) return -1; | ||
| 710 | + if (env == nullptr) return AsyncWrap::kInvalidAsyncId; | ||
| 706 | 711 | return env->trigger_async_id(); | |
| 707 | 712 | } | |
| 708 | 713 | ||
@@ -727,7 +732,7 @@ async_context EmitAsyncInit(Isolate* isolate, | |||
| 727 | 732 | CHECK_NOT_NULL(env); | |
| 728 | 733 | ||
| 729 | 734 | // Initialize async context struct | |
| 730 | - if (trigger_async_id == -1) | ||
| 735 | + if (trigger_async_id == AsyncWrap::kInvalidAsyncId) | ||
| 731 | 736 | trigger_async_id = env->get_default_trigger_async_id(); | |
| 732 | 737 | ||
| 733 | 738 | async_context context = { | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -108,10 +108,12 @@ class AsyncWrap : public BaseObject { | |||
| 108 | 108 | AsyncWrap(Environment* env, | |
| 109 | 109 | v8::Local<v8::Object> object, | |
| 110 | 110 | ProviderType provider, | |
| 111 | - double execution_async_id = -1); | ||
| 111 | + double execution_async_id = kInvalidAsyncId); | ||
| 112 | 112 | ||
| 113 | 113 | virtual ~AsyncWrap(); | |
| 114 | 114 | ||
| 115 | + static constexpr double kInvalidAsyncId = -1; | ||
| 116 | + | ||
| 115 | 117 | static v8::Local<v8::FunctionTemplate> GetConstructorTemplate( | |
| 116 | 118 | Environment* env); | |
| 117 | 119 | ||
@@ -137,6 +139,8 @@ class AsyncWrap : public BaseObject { | |||
| 137 | 139 | static void EmitAfter(Environment* env, double async_id); | |
| 138 | 140 | static void EmitPromiseResolve(Environment* env, double async_id); | |
| 139 | 141 | ||
| 142 | + void EmitDestroy(); | ||
| 143 | + | ||
| 140 | 144 | void EmitTraceEventBefore(); | |
| 141 | 145 | static void EmitTraceEventAfter(ProviderType type, double async_id); | |
| 142 | 146 | void EmitTraceEventDestroy(); | |
@@ -149,7 +153,8 @@ class AsyncWrap : public BaseObject { | |||
| 149 | 153 | ||
| 150 | 154 | inline double get_trigger_async_id() const; | |
| 151 | 155 | ||
| 152 | - void AsyncReset(double execution_async_id = -1, bool silent = false); | ||
| 156 | + void AsyncReset(double execution_async_id = kInvalidAsyncId, | ||
| 157 | + bool silent = false); | ||
| 153 | 158 | ||
| 154 | 159 | // Only call these within a valid HandleScope. | |
| 155 | 160 | v8::MaybeLocal<v8::Value> MakeCallback(const v8::Local<v8::Function> cb, | |
@@ -202,7 +207,7 @@ class AsyncWrap : public BaseObject { | |||
| 202 | 207 | inline AsyncWrap(); | |
| 203 | 208 | const ProviderType provider_type_; | |
| 204 | 209 | // Because the values may be Reset(), cannot be made const. | |
| 205 | - double async_id_ = -1; | ||
| 210 | + double async_id_ = kInvalidAsyncId; | ||
| 206 | 211 | double trigger_async_id_; | |
| 207 | 212 | }; | |
| 208 | 213 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -383,14 +383,13 @@ class Parser : public AsyncWrap, public StreamListener { | |||
| 383 | 383 | ||
| 384 | 384 | ||
| 385 | 385 | static void Free(const FunctionCallbackInfo<Value>& args) { | |
| 386 | - Environment* env = Environment::GetCurrent(args); | ||
| 387 | 386 | Parser* parser; | |
| 388 | 387 | ASSIGN_OR_RETURN_UNWRAP(&parser, args.Holder()); | |
| 389 | 388 | ||
| 390 | 389 | // Since the Parser destructor isn't going to run the destroy() callbacks | |
| 391 | 390 | // it needs to be triggered manually. | |
| 392 | 391 | parser->EmitTraceEventDestroy(); | |
| 393 | - parser->EmitDestroy(env, parser->get_async_id()); | ||
| 392 | + parser->EmitDestroy(); | ||
| 394 | 393 | } | |
| 395 | 394 | ||
| 396 | 395 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,53 @@ | |||
| 1 | + 'use strict'; | ||
| 2 | + const common = require('../common'); | ||
| 3 | + const assert = require('assert'); | ||
| 4 | + const { createHook } = require('async_hooks'); | ||
| 5 | + const http = require('http'); | ||
| 6 | + | ||
| 7 | + // Regression test for https://github.com/nodejs/node/issues/19859. | ||
| 8 | + // Checks that matching destroys are emitted when creating new/reusing old http | ||
| 9 | + // parser instances. | ||
| 10 | + | ||
| 11 | + const httpParsers = []; | ||
| 12 | + const dupDestroys = []; | ||
| 13 | + const destroyed = []; | ||
| 14 | + | ||
| 15 | + createHook({ | ||
| 16 | + init(asyncId, type, triggerAsyncId, resource) { | ||
| 17 | + if (type === 'HTTPPARSER') { | ||
| 18 | + httpParsers.push(asyncId); | ||
| 19 | + } | ||
| 20 | + }, | ||
| 21 | + destroy(asyncId) { | ||
| 22 | + if (destroyed.includes(asyncId)) { | ||
| 23 | + dupDestroys.push(asyncId); | ||
| 24 | + } else { | ||
| 25 | + destroyed.push(asyncId); | ||
| 26 | + } | ||
| 27 | + } | ||
| 28 | + }).enable(); | ||
| 29 | + | ||
| 30 | + const server = http.createServer((req, res) => { | ||
| 31 | + res.end(); | ||
| 32 | + }); | ||
| 33 | + | ||
| 34 | + server.listen(common.mustCall(() => { | ||
| 35 | + http.get({ port: server.address().port }, common.mustCall(() => { | ||
| 36 | + server.close(common.mustCall(() => { | ||
| 37 | + server.listen(common.mustCall(() => { | ||
| 38 | + http.get({ port: server.address().port }, common.mustCall(() => { | ||
| 39 | + server.close(common.mustCall(() => { | ||
| 40 | + setTimeout(common.mustCall(verify), 200); | ||
| 41 | + })); | ||
| 42 | + })); | ||
| 43 | + })); | ||
| 44 | + })); | ||
| 45 | + })); | ||
| 46 | + })); | ||
| 47 | + | ||
| 48 | + function verify() { | ||
| 49 | + assert.strictEqual(httpParsers.length, 4); | ||
| 50 | + | ||
| 51 | + assert.strictEqual(dupDestroys.length, 0); | ||
| 52 | + httpParsers.forEach((id) => assert.ok(destroyed.includes(id))); | ||
| 53 | + } | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments