Skip to content
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

Detecting if a child process spawned successfully #1191

Closed
pushkin- opened this issue Mar 31, 2018 · 5 comments
Closed

Detecting if a child process spawned successfully #1191

pushkin- opened this issue Mar 31, 2018 · 5 comments

Comments

@pushkin-
Copy link

pushkin- commented Mar 31, 2018

  • Node.js Version: 7.9.0
  • OS: Windows 10
  • Scope (install, code, runtime, meta, other?): Code
  • Module (and version) (if relevant): child_process

Is there anyway to detect if a process has successfully spawned? There's an error event that I can listen to, but no success event, so it seems that I have no guarantee that the process successfully spawned until I start actually writing to its streams and get errors.

I have found that I can check proc.pid right after spawning, and if I pass in a faulty path, it's undefined. If I pass in the correct path, it's set to a number, which seems promising. However, someone on SO said that the spawning might still fail after the OS gives back a pid.

What exactly is guaranteed after the spawn function returns? At what point in the spawning process are we? And can I rely on this proc.pid === undefined technique? If not, how can I at least asynchronously know if the process successfully spawned? Why is there no success callback?

@ORESoftware
Copy link

ORESoftware commented Apr 1, 2018

One thing you could do, is in the child process, write to stdout "spawned successfully", read from stdout in the parent process, and then wait for that message.

const k = cp.spawn('bash');
let stdout = '';

k.on('data', function(d){
  stdout+= String(d);
 if(stdout.match(/spawned successfully/)){
     // do your thing
  }
});

@addaleax
Copy link
Member

addaleax commented Apr 1, 2018

I’m pretty sure there was some very similar issue here a while ago, but I can’t seem to find it … anyway:

Is there anyway to detect if a process has successfully spawned?

Sadly, no, not in the general case.

I have no guarantee that the process successfully spawned until I start actually writing to its streams and get errors.

Yup, that’s correct. libuv does a best-effort thing here, but it’s impossible to get a guaranteed result without resorting to e.g. polling techniques that look up the process pid and what that process is currently doing.

I have found that I can check proc.pid right after spawning, and if I pass in a faulty path, it's undefined. If I pass in the correct path, it's set to a number, which seems promising. However, someone on SO said that the spawning might still fail after the OS gives back a pid.

Part of the problem here is that there is no clear line for determining what a “failed” spawn attempt means – at what point do you consider a process spawned successfully? There can be errors at any point during process setup.

What exactly is guaranteed after the spawn function returns?

On Unix, that the execve() system call was entered in the child process, and it succeeded in loading the relevant parts of the target executable into memory.

On Windows, a similar thing goes for CreateProcess().

Either way, there are still plenty of reasons why starting a process might fail – missing DLLs/shared libraries, memory exhaustion while running setup code, etc.

At what point in the spawning process are we?

If the spawn() call succeeds, all you know that it’s up to the OS and the spawned process. No code from Node.js/libuv will be executed anymore inside the child.

And can I rely on this proc.pid === undefined technique?

For checking whether the executable could be found, yes, that’s reliable.

If not, how can I at least asynchronously know if the process successfully spawned?

The only thing that comes to my mind would be polling the OS’s way of providing information about the process tree in general.

Why is there no success callback?

When, and most importantly, from where would that callback be called? spawn() finishing means that the OS and the target executable’s code are in charge now, so Node.js can’t make the process do something like saying “I’m good to go”.

Node.js Version: 7.9.0

(Side note: Node 7 has been unmaintained for ~ 9 months, you might want to consider upgrading to an actively maintained version. Here’s the schedule. :))

@pushkin-
Copy link
Author

pushkin- commented Apr 1, 2018

@addaleax Thanks for all the info. I'm running an outdated Node, because I'm running an older Electron which uses that Node version.

@pushkin- pushkin- closed this as completed Apr 1, 2018
@ORESoftware
Copy link

ORESoftware commented Apr 1, 2018

@pushkin- no problem

@arashmad
Copy link

arashmad commented Jul 13, 2020

One thing you could do, is in the child process, write to stdout "spawned successfully", read from stdout in the parent process, and then wait for that message.

const k = cp.spawn('bash');
let stdout = '';

k.on('data', function(d){
  stdout+= String(d);
 if(stdout.match(/spawned successfully/)){
     // do your thing
  }
});

Thank you so much @ORESoftware - simple and handy

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants