Skip to content

child_process: fire close event from stdio - #22892

Closed
koh110 wants to merge 1 commit into
nodejs:masterfrom
koh110:close_event
Closed

child_process: fire close event from stdio#22892
koh110 wants to merge 1 commit into
nodejs:masterfrom
koh110:close_event

Conversation

@koh110

@koh110koh110 commented Sep 17, 2018

Copy link
Copy Markdown
Contributor

Event of close does not fire when giving for stdio option that type is wrap.
For example, if we set event listener to net.server and giving child_process, that events never fire.

Checklist
  • make -j4 test (UNIX), or vcbuild test (Windows) passes
  • tests and/or benchmarks are included
  • documentation is changed or added
  • commit message follows commit guidelines

@nodejs-github-botnodejs-github-bot added the child_process Issues and PRs related to the child_process subsystem. label Sep 17, 2018
Comment threadlib/internal/child_process.js Outdated

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think this would lead to the event handler being called with a wrong this value, and I think this might not work if there is more than one listener (because stream._events.close would be an array then).

Could we use the listener in the lines below, and call stream.emit('close') from there?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

I see. It might not work when events is an array.

I want to fix.
createSocket create new Socket object and sharing only handle of old socket.
Therefore, we can't call old close events.
How do i fix it best ?

https://github.com/nodejs/node/blob/5a3e445304f3920590b2ae1d1237fe7615572a44/lib/internal/child_process.js#L274
https://github.com/nodejs/node/blob/5a3e445304f3920590b2ae1d1237fe7615572a44/lib/internal/child_process.js#L377

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Therefore, we can't call old close events.

I’m not sure I understand this – Can you explain more? i.e. what wouldn’t work if we add stream.emit('close'); in the callback below?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

I was misunderstanding. It could use stream.emit('close'), if new stream object have old stream object instead of having _events.

I am going to fix.

if (stream._stdio) {
stream._stdio.emit('close');
}
 handle: handle,
- _events: events + _stdio: stdio

@koh110

Copy link
Copy Markdown
ContributorAuthor

@addaleax Hi! I fixed this code. Can you review it ?

Comment threadlib/internal/child_process.js Outdated

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Shouldn’t this go in the stream.socket.on('close', () => { handler below?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

@addaleax I could do it. I fixed and push this code. Please check it.

@addaleax

Copy link
Copy Markdown
Member

@addaleaxaddaleax left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM but we probably need to address one thing before this can finally be merged :)

Comment threadlib/internal/child_process.js Outdated

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

So … the code above (https://github.com/nodejs/node/pull/22892/files#diff-f45eb699237c2e38dc9b49b588933c11R923) reads like stdio could be:

  • A native stream handle
  • An object with a handle property which is a native stream handle
  • An object with a _handle property which is a native stream handle

The path that is typically taken for e.g. net.Sockets would be the third one, I think. We should probably look into deprecating at least the first two, but … all that’s a different story and not really for this PR.

What matters is that stdio does not need to be any kind of particular object; most of the time, it’s a net.Socket or similar, but it could also just be { handle: someNativeHandle }. Even though that’s a bad idea imo, the code above points to this being a possibility. This means that the stream._stdio.emit() call above might fail, because emit() might not be available?

I guess a simple solution would be to turn the if (stream._stdio) { conditional into if (stream._stdio && typeof stream._stdio.emit === 'function') { ?

@koh110koh110Sep 25, 2018

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

I see. I will fix other PR.

I came up with a way when object is pushed. How about this?
Should it be judged when emit()?

const a = {
type: 'wrap',
wrapType: getHandleWrapType(handle),
handle: handle
};
if (typeof stdio.emit === 'function') {
a._stdio = stdio;
}
acc.push(a);

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Or how about if (stream._stdio instanceof EventEmitter)?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@koh110 I’m not sure. instanceof EventEmitter is probably fine, too?

I would prefer for the _stdio property to be present consistently, though – either it’s always there or always missing.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

@addaleax Yeah, you right. I completely agree. I was wrong.

I would prefer for the _stdio property to be present consistently,

I feel that if (stream._stdio && stream._stdio instanceof EventEmitter) { is more meaningful than if(stream._stdio && typeof stream._stdio.emit === 'function') {. EventEmitter may be changed to WritableStream. What do you think about it?

@koh110

Copy link
Copy Markdown
ContributorAuthor

@addaleax I fixed it. Check please.

@koh110

Copy link
Copy Markdown
ContributorAuthor

@nodejs/child_process It needs another approval. Please review it.

@koh110

Copy link
Copy Markdown
ContributorAuthor

Anyone else approve ?

@Trott

Copy link
Copy Markdown
Member

@nodejs/child_process Can someone review this?

@Trott

Copy link
Copy Markdown
Member

(Also: @addaleax Can you confirm this LGTY still?)

@addaleaxaddaleax added the author ready PRs that have at least one approval, no pending requests for changes, and a CI started. label Nov 24, 2018
@addaleax

Copy link
Copy Markdown
Member

@Trott

Copy link
Copy Markdown
Member

Test fails on Windows in CI:

00:36:32 not ok 64 parallel/test-child-process-server-close00:36:32 ---00:36:32 duration_ms: 0.15200:36:32 severity: fail00:36:32 exitcode: 100:36:32 stack: |-00:36:32 internal/child_process.js:37200:36:32 throw errnoException(err, 'spawn');00:36:32 ^00:36:32 00:36:32 Error: spawn ENOTSUP00:36:32 at ChildProcess.spawn (internal/child_process.js:372:11)00:36:32 at spawn (child_process.js:543:9)00:36:32 at Server.net.createServer (c:\workspace\node-test-binary-windows\test\parallel\test-child-process-server-close.js:12:3)00:36:32 at Server.emit (events.js:189:13)00:36:32 at TCP.onconnection (net.js:1507:8)00:36:32 ...

@TrottTrott removed the author ready PRs that have at least one approval, no pending requests for changes, and a CI started. label Nov 25, 2018
Trott
Trott previously requested changes Nov 25, 2018

@TrottTrott left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Test not passing on Windows...

@koh110

koh110 commented Nov 28, 2018

Copy link
Copy Markdown
ContributorAuthor

@Trott I fixed test. I think dir command might be too heavy on Windows.

Travis is failed, but it is only API rate limit. I passed this lint in local.

++node -p 'JSON.parse(process.argv[1])[0].url''{ "message": "API rate limit exceeded for 35.239.89.243. (But here'\''s the good news: Authenticated requests get a higher rate limit. Check out the documentation for more details.)", "documentation_url": "https://developer.github.com/v3/#rate-limiting"}'

Would you execute CI?

@Trott

Copy link
Copy Markdown
Member

@koh110

Copy link
Copy Markdown
ContributorAuthor

@Trott I fixed fluky test. I think server would close before client.
Would you execute CI?

@Trott

Trott commented Jan 7, 2019

Copy link
Copy Markdown
Member

@koh110

koh110 commented Jan 8, 2019

Copy link
Copy Markdown
ContributorAuthor

@Trott I am sorry for taking up so much of your time. Please execute CI.

I found out common.mustCall should not be used in data event.

Sometimes this code returns v10.0.0 and \n.

spawn(process.execPath,['-v'],{stdio: ['ignore',conn,'ignore']});

I removed common.mustCall from handler of data event. I pray for passing tests 🙏

@gireeshpunathil

Copy link
Copy Markdown
Member

@koh110

Copy link
Copy Markdown
ContributorAuthor

some test not passing but i think that it unconnected this fix.
Would it be good to do anything?

@Trott

Copy link
Copy Markdown
Member

@koh110

koh110 commented Jan 17, 2019

Copy link
Copy Markdown
ContributorAuthor

Why does it throw ENOTSUP on windows... 😢
it seems windows couldn't do node -v just vs2017.

@koh110

Copy link
Copy Markdown
ContributorAuthor

Windows accept only UV_TTY and UV_NAMED_PIPE...

if (stream->type==UV_TTY) {
stream_handle= ((uv_tty_t*) stream)->handle;
crt_flags=FOPEN | FDEV;
} elseif (stream->type==UV_NAMED_PIPE&&
stream->flags&UV_HANDLE_CONNECTION) {
stream_handle= ((uv_pipe_t*) stream)->handle;
crt_flags=FOPEN | FPIPE;
} else {
stream_handle=INVALID_HANDLE_VALUE;
crt_flags=0;
}

@koh110

Copy link
Copy Markdown
ContributorAuthor

Whould stream->type be checked before spawn?

@Trott

Trott commented Mar 1, 2019

Copy link
Copy Markdown
Member

Maybe someone on @nodejs/platform-windows can help out or at least give a nudge in the right direction?

@bzoz

bzoz commented Mar 4, 2019

Copy link
Copy Markdown
Contributor

Passing sockets as stdio handles is not supported by libuv under Windows. The internet says it is possible, but that would require some nontrivial changes to libuv.

Maybe the test can use named pipes?

@koh110

Copy link
Copy Markdown
ContributorAuthor

Yes! Named pipes seems working!! Thank you so much! @Trott@bzoz
I will add document Passing sockets is not supported Windows with other PR. And I will challenge to commit libuv if I can.

This commit skipped over my code. So, i modified a few line. Could you review and CI again? @addaleax

@addaleax

Copy link
Copy Markdown
Member

CI: https://ci.nodejs.org/job/node-test-pull-request/21302/

@Trott Can your request-changes be dismissed if CI is green?

@Trott

Trott commented Mar 7, 2019

Copy link
Copy Markdown
Member

@Trott Can your request-changes be dismissed if CI is green?

Yes.

@addaleax

Copy link
Copy Markdown
Member

Landed in 1133e0b, thanks for the PR! 🎉

@addaleaxaddaleax closed this Mar 7, 2019
addaleax pushed a commit that referenced this pull request Mar 7, 2019
PR-URL: #22892
Reviewed-By: Anna Henningsen <anna@addaleax.net>
@koh110
koh110 deleted the close_event branch March 12, 2019 10:27
BridgeAR pushed a commit to BridgeAR/node that referenced this pull request Mar 12, 2019
PR-URL: nodejs#22892
Reviewed-By: Anna Henningsen <anna@addaleax.net>
BridgeAR pushed a commit that referenced this pull request Mar 14, 2019
PR-URL: #22892
Reviewed-By: Anna Henningsen <anna@addaleax.net>
danbev pushed a commit that referenced this pull request Mar 19, 2019
PR-URL: #26604
Refs: #22892 (comment)
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Bartosz Sosnowski <bartosz@janeasystems.com>
targos pushed a commit to targos/node that referenced this pull request Mar 27, 2019
PR-URL: nodejs#26604
Refs: nodejs#22892 (comment)
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Bartosz Sosnowski <bartosz@janeasystems.com>
targos pushed a commit that referenced this pull request Mar 27, 2019
PR-URL: #26604
Refs: #22892 (comment)
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Bartosz Sosnowski <bartosz@janeasystems.com>
BethGriggs pushed a commit that referenced this pull request Apr 17, 2019
PR-URL: #26604
Refs: #22892 (comment)
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Bartosz Sosnowski <bartosz@janeasystems.com>
MylesBorins pushed a commit that referenced this pull request May 16, 2019
PR-URL: #26604
Refs: #22892 (comment)
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Bartosz Sosnowski <bartosz@janeasystems.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

child_processIssues and PRs related to the child_process subsystem.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants

@koh110@addaleax@Trott@gireeshpunathil@bzoz@nodejs-github-bot