Skip to content

Commit 5390d7e

Browse files
addaleaxMylesBorins
authored andcommitted
http2: move uv_prepare handle to Http2Session
As far as I understand it, `Nghttp2Session` should not be concerned about how its consumers handle I/O. PR-URL: #16461 Reviewed-By: Anatoli Papirovski <apapirovski@mac.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Franziska Hinkelmann <franziska.hinkelmann@gmail.com>
1 parent 889f42a commit 5390d7e

File tree

4 files changed

+55
-51
lines changed

4 files changed

+55
-51
lines changed

src/node_http2.cc

+39-2
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,45 @@ Http2Options::Http2Options(Environment* env) {
6969
}
7070
}
7171

72-
void Http2Session::OnFreeSession() {
73-
::delete this;
72+
73+
Http2Session::Http2Session(Environment* env,
74+
Local<Object> wrap,
75+
nghttp2_session_type type)
76+
: AsyncWrap(env, wrap, AsyncWrap::PROVIDER_HTTP2SESSION),
77+
StreamBase(env) {
78+
Wrap(object(), this);
79+
80+
Http2Options opts(env);
81+
82+
padding_strategy_ = opts.GetPaddingStrategy();
83+
84+
Init(type, *opts);
85+
86+
// For every node::Http2Session instance, there is a uv_prepare_t handle
87+
// whose callback is triggered on every tick of the event loop. When
88+
// run, nghttp2 is prompted to send any queued data it may have stored.
89+
prep_ = new uv_prepare_t();
90+
uv_prepare_init(env->event_loop(), prep_);
91+
prep_->data = static_cast<void*>(this);
92+
uv_prepare_start(prep_, [](uv_prepare_t* t) {
93+
Http2Session* session = static_cast<Http2Session*>(t->data);
94+
session->SendPendingData();
95+
});
96+
}
97+
98+
Http2Session::~Http2Session() {
99+
CHECK_EQ(false, persistent().IsEmpty());
100+
ClearWrap(object());
101+
persistent().Reset();
102+
CHECK_EQ(true, persistent().IsEmpty());
103+
104+
// Stop the loop
105+
CHECK_EQ(uv_prepare_stop(prep_), 0);
106+
auto prep_close = [](uv_handle_t* handle) {
107+
delete reinterpret_cast<uv_prepare_t*>(handle);
108+
};
109+
uv_close(reinterpret_cast<uv_handle_t*>(prep_), prep_close);
110+
prep_ = nullptr;
74111
}
75112

76113
ssize_t Http2Session::OnMaxFrameSizePadding(size_t frameLen,

src/node_http2.h

+7-20
Original file line numberDiff line numberDiff line change
@@ -343,24 +343,8 @@ class Http2Session : public AsyncWrap,
343343
public:
344344
Http2Session(Environment* env,
345345
Local<Object> wrap,
346-
nghttp2_session_type type) :
347-
AsyncWrap(env, wrap, AsyncWrap::PROVIDER_HTTP2SESSION),
348-
StreamBase(env) {
349-
Wrap(object(), this);
350-
351-
Http2Options opts(env);
352-
353-
padding_strategy_ = opts.GetPaddingStrategy();
354-
355-
Init(env->event_loop(), type, *opts);
356-
}
357-
358-
~Http2Session() override {
359-
CHECK_EQ(false, persistent().IsEmpty());
360-
ClearWrap(object());
361-
persistent().Reset();
362-
CHECK_EQ(true, persistent().IsEmpty());
363-
}
346+
nghttp2_session_type type);
347+
~Http2Session() override;
364348

365349
static void OnStreamAllocImpl(size_t suggested_size,
366350
uv_buf_t* buf,
@@ -369,9 +353,8 @@ class Http2Session : public AsyncWrap,
369353
const uv_buf_t* bufs,
370354
uv_handle_type pending,
371355
void* ctx);
372-
protected:
373-
void OnFreeSession() override;
374356

357+
protected:
375358
ssize_t OnMaxFrameSizePadding(size_t frameLength,
376359
size_t maxPayloadLen);
377360

@@ -449,6 +432,9 @@ class Http2Session : public AsyncWrap,
449432
return 0;
450433
}
451434

435+
uv_loop_t* event_loop() const override {
436+
return env()->event_loop();
437+
}
452438
public:
453439
void Consume(Local<External> external);
454440
void Unconsume();
@@ -496,6 +482,7 @@ class Http2Session : public AsyncWrap,
496482

497483
// use this to allow timeout tracking during long-lasting writes
498484
uint32_t chunks_sent_since_last_write_ = 0;
485+
uv_prepare_t* prep_ = nullptr;
499486

500487
char stream_buf_[kAllocBufferSize];
501488
};

src/node_http2_core-inl.h

+5-24
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,8 @@ inline ssize_t Nghttp2Session::OnStreamReadFD(nghttp2_session* session,
193193
uv_fs_t read_req;
194194

195195
if (length > 0) {
196-
numchars = uv_fs_read(handle->loop_,
196+
// TODO(addaleax): Never use synchronous I/O on the main thread.
197+
numchars = uv_fs_read(handle->event_loop(),
197198
&read_req,
198199
fd, &data, 1,
199200
offset, nullptr);
@@ -541,11 +542,9 @@ inline void Nghttp2Session::SendPendingData() {
541542
// Initialize the Nghttp2Session handle by creating and
542543
// assigning the Nghttp2Session instance and associated
543544
// uv_loop_t.
544-
inline int Nghttp2Session::Init(uv_loop_t* loop,
545-
const nghttp2_session_type type,
546-
nghttp2_option* options,
547-
nghttp2_mem* mem) {
548-
loop_ = loop;
545+
inline int Nghttp2Session::Init(const nghttp2_session_type type,
546+
nghttp2_option* options,
547+
nghttp2_mem* mem) {
549548
session_type_ = type;
550549
DEBUG_HTTP2("Nghttp2Session %s: initializing session\n", TypeName());
551550
destroying_ = false;
@@ -581,14 +580,6 @@ inline int Nghttp2Session::Init(uv_loop_t* loop,
581580
nghttp2_option_del(opts);
582581
}
583582

584-
// For every node::Http2Session instance, there is a uv_prep_t handle
585-
// whose callback is triggered on every tick of the event loop. When
586-
// run, nghttp2 is prompted to send any queued data it may have stored.
587-
uv_prepare_init(loop_, &prep_);
588-
uv_prepare_start(&prep_, [](uv_prepare_t* t) {
589-
Nghttp2Session* session = ContainerOf(&Nghttp2Session::prep_, t);
590-
session->SendPendingData();
591-
});
592583
return ret;
593584
}
594585

@@ -601,19 +592,9 @@ inline int Nghttp2Session::Free() {
601592
CHECK(session_ != nullptr);
602593
#endif
603594
DEBUG_HTTP2("Nghttp2Session %s: freeing session\n", TypeName());
604-
// Stop the loop
605-
CHECK_EQ(uv_prepare_stop(&prep_), 0);
606-
auto PrepClose = [](uv_handle_t* handle) {
607-
Nghttp2Session* session =
608-
ContainerOf(&Nghttp2Session::prep_,
609-
reinterpret_cast<uv_prepare_t*>(handle));
610-
session->OnFreeSession();
611-
};
612-
uv_close(reinterpret_cast<uv_handle_t*>(&prep_), PrepClose);
613595
nghttp2_session_terminate_session(session_, NGHTTP2_NO_ERROR);
614596
nghttp2_session_del(session_);
615597
session_ = nullptr;
616-
loop_ = nullptr;
617598
DEBUG_HTTP2("Nghttp2Session %s: session freed\n", TypeName());
618599
return 1;
619600
}

src/node_http2_core.h

+4-5
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,6 @@ class Nghttp2Session {
9393
public:
9494
// Initializes the session instance
9595
inline int Init(
96-
uv_loop_t*,
9796
const nghttp2_session_type type = NGHTTP2_SESSION_SERVER,
9897
nghttp2_option* options = nullptr,
9998
nghttp2_mem* mem = nullptr);
@@ -176,7 +175,6 @@ class Nghttp2Session {
176175
int error_code) {}
177176
virtual ssize_t GetPadding(size_t frameLength,
178177
size_t maxFrameLength) { return 0; }
179-
virtual void OnFreeSession() {}
180178
virtual void AllocateSend(uv_buf_t* buf) = 0;
181179

182180
virtual bool HasGetPaddingCallback() { return false; }
@@ -200,8 +198,11 @@ class Nghttp2Session {
200198
virtual void OnTrailers(Nghttp2Stream* stream,
201199
const SubmitTrailers& submit_trailers) {}
202200

203-
private:
204201
inline void SendPendingData();
202+
203+
virtual uv_loop_t* event_loop() const = 0;
204+
205+
private:
205206
inline void HandleHeadersFrame(const nghttp2_frame* frame);
206207
inline void HandlePriorityFrame(const nghttp2_frame* frame);
207208
inline void HandleDataFrame(const nghttp2_frame* frame);
@@ -282,8 +283,6 @@ class Nghttp2Session {
282283
static Callbacks callback_struct_saved[2];
283284

284285
nghttp2_session* session_;
285-
uv_loop_t* loop_;
286-
uv_prepare_t prep_;
287286
nghttp2_session_type session_type_;
288287
std::unordered_map<int32_t, Nghttp2Stream*> streams_;
289288
bool destroying_ = false;

0 commit comments

Comments
 (0)