Skip to content
This repository has been archived by the owner on Apr 22, 2023. It is now read-only.

tls: Closing parent socket also closes the tls sock #25642

Closed
wants to merge 1 commit into from

Conversation

dnakamura
Copy link

Fixes #25365 . At the moment if you close the parent socket of a a TLS socket the TLS socket is not aware of this and will segfault when you attempt to perform and IO operation on it. Further, if you close the parent socket and then the TLS socket, the parent socket will emit the close event twice (and the TLS socket wont fire at all). If you change the order the results are reversed, ie. closing the TLS then the parent socket will result in the TLS socket firing the close event twice and the parent socket wont fire at all.

This patch moves toward linking the parent and tls sockets. Calling destroy() on either of the the sockets causes both sockets to be destroyed and the close event emitted for both of them

@@ -238,6 +238,7 @@ function TLSSocket(socket, options) {

if (socket) {
this._parent = socket;
socket._destroy = function(exception){self._destroy(exception)};

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not simply this._destroy.bind(this);?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm newish to javascript and I didn't know that was a thing

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would do:

function(err) {
  self._destroy(err);
}

Last time I check it - bind was kind of slow.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@indutny Oh, okay. Thanks for the info :-)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This one is still there ;)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This one wasn't fixed. Please make it span multiple lines.

@mhdawson
Copy link
Member

mhdawson commented Jul 8, 2015

@indutny could you review this as well since one of your recent commits ( dnakamura/node@bada87b#diff-04c3a6bcf355f2e05e7700c1b253d475) looks like it addressed a similar parent/child related issue.

@@ -456,7 +456,8 @@ Socket.prototype._destroy = function(exception, cb) {
if (cb) cb(exception);
if (exception && !self._writableState.errorEmitted) {
process.nextTick(function() {
self.emit('error', exception);
for(var s = self; s !== null; s = s._parent)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for (

@indutny
Copy link
Member

indutny commented Jul 8, 2015

@dnakamura I wonder if we may consider backporting nodejs/node@9b6b05556 instead?

@dnakamura
Copy link
Author

@Induty As far as I can tell, nodejs/node@9b6b055 does not fix the problem (still able to reproduce on latest io.js). Also I have to double check the code but I think it may already be backported

});
this._handle.onread = noop;
this._handle = null;
for(var s = this; s !== null; s = s._parent){
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for (...)

@indutny
Copy link
Member

indutny commented Jul 10, 2015

@dnakamura you are absolutely right. It just looked strikingly similar, so I thought it might need the backport. Looked through the changes and they are looking good to me except few nits.

@mhdawson mhdawson self-assigned this Jul 17, 2015
@mhdawson mhdawson added this to the 0.12.8 milestone Jul 17, 2015
@dnakamura
Copy link
Author

@indutny , @thefourtheye took your changes into account, can you take another look.
(also, I added another commit, so that I wouldn't destroy your comments on the original commit. Will squash it when everybody agrees fix is good.)

for (var s = this; s !== null; s = s._parent){
timers.unenroll(s);
s._connecting = false;
s.readable = s.writable = false;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we are writing like this, why not just

s._connecting = s.readable = s.writable = false;

then?

@indutny
Copy link
Member

indutny commented Jul 22, 2015

LGTM, except some style nits. May I ask you to fix them before I will land this PR?

(It is going to be fun to forward-port it to io.js. I should probably do it myself right after landing it in v0.12)

@dnakamura
Copy link
Author

@indutny Fixed style nits, can you take a look?


for (var s = this; s !== null; s = s._parent)
timers.unenroll(s);
for (var s = this; s !== null; s = s._parent){
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Space between ) and {. Didn't make lint complain about it?

@indutny
Copy link
Member

indutny commented Aug 5, 2015

Few last nits, thanks!

@dnakamura dnakamura force-pushed the tlsfix branch 2 times, most recently from 8884c5c to be30464 Compare August 7, 2015 13:38
@dnakamura
Copy link
Author

@indutny ok that should be all of them

@dnakamura
Copy link
Author

@indutny ok, hopefully now I've got it 😄

@@ -238,6 +239,9 @@ function TLSSocket(socket, options) {

if (socket) {
this._parent = socket;
socket._destroy = function(exception) {
self._destroy(exception)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Semicolon at the end?

@dnakamura
Copy link
Author

@thefourtheye fixed.

@indutny
Copy link
Member

indutny commented Aug 17, 2015

Awesome LGTM. @thefourtheye may I have your LGTM as well? ;)

@thefourtheye
Copy link

@indutny Changes are straight forward. LGTMT :)

@indutny
Copy link
Member

indutny commented Aug 18, 2015

@mhdawson @thefourtheye where should I land this?

@thefourtheye
Copy link

@indutny I am not familiar with this repo's pr landing process but going by the tags on this PR I would say v0.12

@jasnell
Copy link
Member

jasnell commented Aug 18, 2015

I can get it landed. FWIW, we use the node-accept-pull-request job in https://jenkins-iojs.nodesource.com/ to land in joyent/node. @orangemocha has all the necessary details on that.

@thefourtheye
Copy link

@jasnell Thanks for the info :-)

@jasnell
Copy link
Member

jasnell commented Aug 18, 2015

@thefourtheye ... btw, I can't seem to find your full name anywhere for the sign off ;-)

@thefourtheye
Copy link

@jasnell Its in nodejs/node's collaborator's list. Sakthipriyan Vairamani :-) It is nice working with you :-)

@jasnell
Copy link
Member

jasnell commented Aug 18, 2015

The pleasure is mine.
Ok, job kicked off... assuming the CI is green, the commit will land (https://jenkins-iojs.nodesource.com/job/node-accept-pull-request/36/)

@jasnell
Copy link
Member

jasnell commented Aug 18, 2015

@dnakamura ... if you're seeing this problem on io.js master also, can I ask for you to go ahead and port this and open a new PR against master on nodejs/node if you haven't done so already? :-)

@jasnell
Copy link
Member

jasnell commented Aug 18, 2015

Hmm.. @dnakamura getting some failures in CI. Not clear if they are related to the change. Same failure on both Windows platforms. https://jenkins-iojs.nodesource.com/job/node-test-commit-windows/nodes=win2008r2/181/

@dnakamura
Copy link
Author

@jasnell: yup it does seem to be me (except test-dns), looking into the root cause now

@dnakamura
Copy link
Author

So as it turns out the issue is because now if the socket is destroyed from an error, both sockets (tls, and parent) emit an error. Since nobody is listening for errors on the parent socket it causes an unhandled error event. My first instinct is to only change the code so it only fires the error event on the lowest socket (from a parent-child view, highest from a protocol stack view). However I'm wondering if it might make more sense to always fire the error event on the same object _destroy() was called on. Thoughts?

@indutny
Copy link
Member

indutny commented Aug 18, 2015

@dnakamura or we may call it a breaking change, land it in nodejs/node repo. And watch for the error events ourselves. Maybe this is better?

@indutny
Copy link
Member

indutny commented Aug 18, 2015

Or just not emit errors on parent socket in v0.12. Technically, emitting close should be enough to let it handle socket state change.

@dnakamura
Copy link
Author

@jasnell Ok that should fix it now. I have a couple tests still failing here, but they also fail on official builds, so I dont think its my fault

@jasnell
Copy link
Member

jasnell commented Aug 27, 2015

As long as it passes CI, LGTM. I'll run it through the checker now.

jasnell pushed a commit that referenced this pull request Aug 27, 2015
PR-URL: #25642
Reviewed-By: jasnell - James M Snell <jasnell@gmail.com>
@jasnell
Copy link
Member

jasnell commented Aug 27, 2015

Landed in 0363cf4

@jasnell jasnell closed this Aug 27, 2015
jBarz pushed a commit to ibmruntimes/node that referenced this pull request Nov 4, 2016
PR-URL: nodejs#25642
Reviewed-By: jasnell - James M Snell <jasnell@gmail.com>
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants