-
Notifications
You must be signed in to change notification settings - Fork 29.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
http_parser: do not dealloc during kOnExecute #2956
Conversation
ac7df35
to
a14e796
Compare
Test is a bit complicated, because the crash happens only on the access to the uninitialized memory. |
What commit or commits introduced the regression? |
class ScopedRetainParser { | ||
public: | ||
ScopedRetainParser(Parser* p) : p_(p) { | ||
p_->refcount_++; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider doing CHECK(p_->refcount_ > 0)
first in this function.
The regression happened at: 1bc4468 |
a14e796
to
8432445
Compare
@bnoordhuis all fixed. |
8432445
to
2900294
Compare
Create 1,000 or 10,000 parser objects and close them from within .execute(). One of them is bound to trigger the crash.
Can you include that in the commit log? Maybe also reference the first line of its commit log, that saves the log spelunker an extra |
@bnoordhuis included. Will work on the test, but it won't be reliable unless started under valgrind. |
Thank you! |
@@ -668,7 +689,10 @@ class Parser : public BaseObject { | |||
char* current_buffer_data_; | |||
StreamResource::Callback<StreamResource::AllocCb> prev_alloc_cb_; | |||
StreamResource::Callback<StreamResource::ReadCb> prev_read_cb_; | |||
int refcount_; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
By the way, you can initialize it to 1 here.
Outside of including a test, don't see anything I would change. LGTM. |
2900294
to
b0e844f
Compare
Force pushed, PTAL |
@@ -504,6 +506,22 @@ class Parser : public BaseObject { | |||
} | |||
|
|||
protected: | |||
class ScopedRetainParser { | |||
public: | |||
explicit ScopedRetainParser(Parser* p) : p_(p) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wouldn't it be better to have a const
here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think that delete
may be called on const
pointer... Am I wrong?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@indutny I just tried this
# include <cstdio>
class Test {
public:
Test(const char * str) : my_str(str) {
}
~Test() {
fprintf(stderr, "Cleaning up");
delete my_str;
}
private:
const char * my_str;
};
int main() {
Test test(new char[50]);
}
with
➜ Desktop g++ Test.cpp && ./a.out
Cleaning up
➜ Desktop
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
-Wall
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@indutny Hmmm, I tried that now. No warnings.
➜ Desktop g++ -Wall Test.cpp && ./a.out
Cleaning up
➜ Desktop
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, I think you're right.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Anyway, I'm changing the refcount of the parser, so it won't work.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@indutny Ah, right. Sorry for the fuss.
`freeParser` deallocates `Parser` instances early if they do not fit into the free list. This does not play well with recent socket consumption change, because it will try to deallocate the parser while executing on its stack. Regression was introduced in: 1bc4468 Fix: nodejs#2928
0007ada
to
485e152
Compare
CI is green. Shall I land it? |
LGTM |
Landed in 229a03f, thank you! |
`freeParser` deallocates `Parser` instances early if they do not fit into the free list. This does not play well with recent socket consumption change, because it will try to deallocate the parser while executing on its stack. Regression was introduced in: 1bc4468 Fix: #2928 PR-URL: #2956 Reviewed-by: Trevor Norris <trev.norris@gmail.com>
Awesome! Thanks guys! 💪 |
`freeParser` deallocates `Parser` instances early if they do not fit into the free list. This does not play well with recent socket consumption change, because it will try to deallocate the parser while executing on its stack. Regression was introduced in: 1bc4468 Fix: #2928 PR-URL: #2956 Reviewed-by: Trevor Norris <trev.norris@gmail.com>
landed in lts-v4.x-staging as bc9f629 |
freeParser
deallocatesParser
instances early if they do not fitinto the free list. This does not play well with recent socket
consumption change, because it will try to deallocate the parser while
executing on its stack.
Fix: #2928
cc @nodejs/collaborators @trevnorris @bnoordhuis