summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGerhard Stoebich <18708370+Flarna@users.noreply.github.com>2019-04-23 00:57:12 +0200
committerAnna Henningsen <anna@addaleax.net>2019-05-03 16:02:55 +0200
commit8876ac5c358114f0f88424f6737ca4b89fc9e6c7 (patch)
tree5b0804517e873f3c08b236104b11f26dd752f941 /src
parent8dae89b396df64e6a9e44cb94efe27809a5a3d89 (diff)
downloadandroid-node-v8-8876ac5c358114f0f88424f6737ca4b89fc9e6c7.tar.gz
android-node-v8-8876ac5c358114f0f88424f6737ca4b89fc9e6c7.tar.bz2
android-node-v8-8876ac5c358114f0f88424f6737ca4b89fc9e6c7.zip
async_hooks: fixup do not reuse HTTPParser
Fix some issues introduced/not fixed via https://github.com/nodejs/node/pull/25094: * Init hook is not emitted for a reused HTTPParser * HTTPParser was still used as resource in init hook * type used in init hook was always HTTPINCOMINGMESSAGE even for client requests * some tests have not been adapted to new resource names With this change the async hooks init event is emitted during a call to Initialize() as the type and resource object is available at this time. As a result Initialize() must be called now which could be seen as breaking change even HTTPParser is not part of documented API. It was needed to put the ClientRequest instance into a wrapper object instead passing it directly as async resource otherwise test-domain-multi fails. I think this is because adding an EventEmitter to a Domain adds a property 'domain' and the presence of this changes the context propagation in domains. Besides that tests still refering to resource HTTPParser have been updated/improved. Fixes: https://github.com/nodejs/node/issues/27467 Fixes: https://github.com/nodejs/node/issues/26961 Refs: https://github.com/nodejs/node/pull/25094 PR-URL: https://github.com/nodejs/node/pull/27477 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Rich Trott <rtrott@gmail.com>
Diffstat (limited to 'src')
-rw-r--r--src/async_wrap.cc31
-rw-r--r--src/async_wrap.h17
-rw-r--r--src/node_http_parser_impl.h18
3 files changed, 40 insertions, 26 deletions
diff --git a/src/async_wrap.cc b/src/async_wrap.cc
index e822255265..0c84b06fdd 100644
--- a/src/async_wrap.cc
+++ b/src/async_wrap.cc
@@ -178,7 +178,7 @@ void AsyncWrap::EmitAfter(Environment* env, double async_id) {
class PromiseWrap : public AsyncWrap {
public:
PromiseWrap(Environment* env, Local<Object> object, bool silent)
- : AsyncWrap(env, object, PROVIDER_PROMISE, -1, silent) {
+ : AsyncWrap(env, object, PROVIDER_PROMISE, kInvalidAsyncId, silent) {
MakeWeak();
}
@@ -388,7 +388,7 @@ static void RegisterDestroyHook(const FunctionCallbackInfo<Value>& args) {
void AsyncWrap::GetAsyncId(const FunctionCallbackInfo<Value>& args) {
AsyncWrap* wrap;
- args.GetReturnValue().Set(-1);
+ args.GetReturnValue().Set(kInvalidAsyncId);
ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder());
args.GetReturnValue().Set(wrap->get_async_id());
}
@@ -415,10 +415,15 @@ void AsyncWrap::AsyncReset(const FunctionCallbackInfo<Value>& args) {
AsyncWrap* wrap;
ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder());
double execution_async_id =
- args[0]->IsNumber() ? args[0].As<Number>()->Value() : -1;
+ args[0]->IsNumber() ? args[0].As<Number>()->Value() : kInvalidAsyncId;
wrap->AsyncReset(execution_async_id);
}
+void AsyncWrap::EmitDestroy() {
+ AsyncWrap::EmitDestroy(env(), async_id_);
+ // Ensure no double destroy is emitted via AsyncReset().
+ async_id_ = kInvalidAsyncId;
+}
void AsyncWrap::QueueDestroyAsyncId(const FunctionCallbackInfo<Value>& args) {
CHECK(args[0]->IsNumber());
@@ -481,7 +486,7 @@ void AsyncWrap::Initialize(Local<Object> target,
// kDefaultTriggerAsyncId: Write the id of the resource responsible for a
// handle's creation just before calling the new handle's constructor.
// After the new handle is constructed kDefaultTriggerAsyncId is set back
- // to -1.
+ // to kInvalidAsyncId.
FORCE_SET_TARGET_FIELD(target,
"async_id_fields",
env->async_hooks()->async_id_fields().GetJSArray());
@@ -569,10 +574,16 @@ AsyncWrap::AsyncWrap(Environment* env,
AsyncReset(execution_async_id, silent);
}
+AsyncWrap::AsyncWrap(Environment* env, v8::Local<v8::Object> object)
+ : BaseObject(env, object),
+ provider_type_(PROVIDER_NONE) {
+ CHECK_GE(object->InternalFieldCount(), 1);
+}
+
AsyncWrap::~AsyncWrap() {
EmitTraceEventDestroy();
- EmitDestroy(env(), get_async_id());
+ EmitDestroy();
}
void AsyncWrap::EmitTraceEventDestroy() {
@@ -612,16 +623,18 @@ void AsyncWrap::AsyncReset(double execution_async_id, bool silent) {
// the resource is pulled out of the pool and put back into use.
void AsyncWrap::AsyncReset(Local<Object> resource, double execution_async_id,
bool silent) {
- if (async_id_ != -1) {
+ CHECK_NE(provider_type(), PROVIDER_NONE);
+
+ if (async_id_ != kInvalidAsyncId) {
// This instance was in use before, we have already emitted an init with
// its previous async_id and need to emit a matching destroy for that
// before generating a new async_id.
- EmitDestroy(env(), async_id_);
+ EmitDestroy();
}
// Now we can assign a new async_id_ to this instance.
- async_id_ =
- execution_async_id == -1 ? env()->new_async_id() : execution_async_id;
+ async_id_ = execution_async_id == kInvalidAsyncId ? env()->new_async_id()
+ : execution_async_id;
trigger_async_id_ = env()->get_default_trigger_async_id();
switch (provider_type()) {
diff --git a/src/async_wrap.h b/src/async_wrap.h
index bcd37bb0c0..20134f4a7b 100644
--- a/src/async_wrap.h
+++ b/src/async_wrap.h
@@ -109,12 +109,18 @@ class AsyncWrap : public BaseObject {
AsyncWrap(Environment* env,
v8::Local<v8::Object> object,
ProviderType provider,
- double execution_async_id = -1);
+ double execution_async_id = kInvalidAsyncId);
+
+ // This constructor creates a reuseable instance where user is responsible
+ // to call set_provider_type() and AsyncReset() before use.
+ AsyncWrap(Environment* env, v8::Local<v8::Object> object);
~AsyncWrap() override;
AsyncWrap() = delete;
+ static constexpr double kInvalidAsyncId = -1;
+
static v8::Local<v8::FunctionTemplate> GetConstructorTemplate(
Environment* env);
@@ -141,6 +147,8 @@ class AsyncWrap : public BaseObject {
static void EmitAfter(Environment* env, double async_id);
static void EmitPromiseResolve(Environment* env, double async_id);
+ void EmitDestroy();
+
void EmitTraceEventBefore();
static void EmitTraceEventAfter(ProviderType type, double async_id);
void EmitTraceEventDestroy();
@@ -155,10 +163,11 @@ class AsyncWrap : public BaseObject {
inline double get_trigger_async_id() const;
void AsyncReset(v8::Local<v8::Object> resource,
- double execution_async_id = -1,
+ double execution_async_id = kInvalidAsyncId,
bool silent = false);
- void AsyncReset(double execution_async_id = -1, bool silent = false);
+ void AsyncReset(double execution_async_id = kInvalidAsyncId,
+ bool silent = false);
// Only call these within a valid HandleScope.
v8::MaybeLocal<v8::Value> MakeCallback(const v8::Local<v8::Function> cb,
@@ -210,7 +219,7 @@ class AsyncWrap : public BaseObject {
bool silent);
ProviderType provider_type_;
// Because the values may be Reset(), cannot be made const.
- double async_id_ = -1;
+ double async_id_ = kInvalidAsyncId;
double trigger_async_id_;
};
diff --git a/src/node_http_parser_impl.h b/src/node_http_parser_impl.h
index a8a8db5547..a354c6fcc5 100644
--- a/src/node_http_parser_impl.h
+++ b/src/node_http_parser_impl.h
@@ -154,14 +154,10 @@ struct StringPtr {
class Parser : public AsyncWrap, public StreamListener {
public:
- Parser(Environment* env, Local<Object> wrap, parser_type_t type)
- : AsyncWrap(env, wrap,
- type == HTTP_REQUEST ?
- AsyncWrap::PROVIDER_HTTPINCOMINGMESSAGE :
- AsyncWrap::PROVIDER_HTTPCLIENTREQUEST),
+ Parser(Environment* env, Local<Object> wrap)
+ : AsyncWrap(env, wrap),
current_buffer_len_(0),
current_buffer_data_(nullptr) {
- Init(type);
}
@@ -426,11 +422,7 @@ class Parser : public AsyncWrap, public StreamListener {
static void New(const FunctionCallbackInfo<Value>& args) {
Environment* env = Environment::GetCurrent(args);
- CHECK(args[0]->IsInt32());
- parser_type_t type =
- static_cast<parser_type_t>(args[0].As<Int32>()->Value());
- CHECK(type == HTTP_REQUEST || type == HTTP_RESPONSE);
- new Parser(env, args.This(), type);
+ new Parser(env, args.This());
}
@@ -443,14 +435,13 @@ class Parser : public AsyncWrap, public StreamListener {
static void Free(const FunctionCallbackInfo<Value>& args) {
- Environment* env = Environment::GetCurrent(args);
Parser* parser;
ASSIGN_OR_RETURN_UNWRAP(&parser, args.Holder());
// Since the Parser destructor isn't going to run the destroy() callbacks
// it needs to be triggered manually.
parser->EmitTraceEventDestroy();
- parser->EmitDestroy(env, parser->get_async_id());
+ parser->EmitDestroy();
}
@@ -526,6 +517,7 @@ class Parser : public AsyncWrap, public StreamListener {
: AsyncWrap::PROVIDER_HTTPCLIENTREQUEST);
parser->set_provider_type(provider);
+ parser->AsyncReset(args[1].As<Object>());
parser->Init(type);
}