Spawn Process in Windows Immediately Exits


#1

I hope I’m missing something simple. I’m trying to figure out why certain node modules are preventing me from being able to spawn a child process from the main process.

Using electron, from the main process I attempt to use the child_process module to spawn a child. The child is another node script. The intention is to start a server in a separate process to make it easy to start/stop it and prevent issues in the main process if something in the server dies. The issue I’m running into though is that, the child script is bare minimum but wont execute. Certain node modules will cause it to crash/exit immediately when spawn is called. The child is currently modified down to this alone

var express = require('express')
setTimeout(function(){ process.exit(1) },4000)

This will exit immediately. If I comment out the first line where it requires express, it will wait 4 seconds then exit as expected. Some modules this behavior, some don’t. The following are a list of modules I have tested and their status

  • lodash - works
  • underscore - works
  • polo - works
  • commander - works
  • async - works
  • q - works
  • request - works
  • socket.io - exits
  • express - exits
  • chalk - exits

Is there something I’m missing that would cause this behavior? Running latest (as of now) version of Electron 0.36.2 which is running node 5.1.1. The machine I’m testing this on currently has node 4.2.4 on it but I have tested it with 5.1.1 as well to make sure there wasn’t an issue there.

Help?


#2

Have you tried copying Atom’s BufferedProcess and BufferedNodeProcess just to see if there is something that you missed perhaps?


#3

I haven’t. What I did was…

  1. Tested the source code on my Mac from the command line with Electron.
  2. Went to Windows VM
  3. Used npm to install electron-prebuilt and electron-packager
  4. Ran electron-packager with…
    electron-packager --platform=win32 --arch=x64 --version=“0.36.2” --output
  5. Launch the exe

When that didn’t work, I went to a command prompt in Windows and cd’d to the /resources/app folder and tried running the source code from there using electron and that doesn’t work either. I ran again from an Administrator command prompt, same issue.

After these didn’t work, I decided to simplify what I had and take just a 2-3 line script and try it that way. The same thing occurs. Do you think that the solution you mentioned would still be viable? I’m not sure what the process is to do that but can look into it if you think that is still a potential solution


#4

I do think it is potentially a solution. I’m not sure that Atom starts servers like what you’re trying to do, but it might help.

Also, if I recall correctly @mark_hahn did some stuff with subprocesses in Atom and might have some insights?


#5

I don’t see how electron could affect what happens in another process. Have you tried spawning your child processes from a simple node app instead of electron?


#6

The code functions normally from the command line as a node app. I’ve been using it for a long time that way. I recently decided to migrate the code into a single npm module (private) and merge it into electron so that I could have a gui for configuration rather than using command line parameters. I can make you an extremely simple application to demonstrate the issue if you’d like.


#7

If you could do that, I would appreciate it. I can’t promise anything, but I’ll take a look.


#8

My experience is that exiting immediately means you have an error happening in your child process. Error reporting back to the parent isn’t very reliable. I know that seems impossible but there is something wrong, like not being able to find express in the node_modules path or something else. Most of my bugs seem impossible until they aren’t.


#9

Maybe I’m having a case of the Monday’s but I attempted to make a simple case to show the issue (did this numerous times last week while trying to find the issue) and wasn’t able to replicate it today. I didn’t have a lot of time to tend to this today. I’m going to continue looking at it over the next few days and will take @mark_hahn last post into consideration. Based on the testing from the other day, I don’t see how this could be the cause but I’m certainly going to attempt to dig deeper again.


#10

Ok, sorry guys (@mark_hahn and @leedohm) , I got tied up with some other stuff and it took me a bit to get back to this.

So, I’ve got a REALLY basic example of me attempting to run this in Windows and it failing. It works on my Mac. Just not in Windows. I tested it in Windows 7 x64.

Download

The above is a zip file contains:
package.json
index.html
index.js
child.js

There will be a single dependency (socket.io) so you’ll need to npm install to grab it before you execute. I was running electron from the command line using version 0.36.2, installed from npm install electron-prebuilt

So… electron . to launch it. The UI is the default with an added button to click. The button will use ipc to send a launch event back to the main process. The main process will attempt to spawn the new process of child.js. As it attempts this, the main process will provide two console logs. One just before the spawn, and one as the child process exits. The child process has a 10 second timeout within so, it should just launch, wait 10 seconds, then exit.

The child.js will also attempt to require(‘socket.io’). If that line is active, the console will show that the child process spawns and exits immediately. If it’s commented out, it will run 10 seconds and then exit.

Socket.io doesn’t have any issues, as mentioned, this works on my Mac. It also works if I run node child.js directly from the command prompt in Windows. So, the issue doesn’t seem to be node, it doesn’t seem to be socket.io. It seems to be something with spawning processes within electron that include this and other modules.

Thoughts?


#11

I had to change the contents of child.js to be:

// var io = require('socket.io')

setTimeout(function() {
  process.exit(1)
},10000);

Otherwise I got a SyntaxError when I clicked the button:

/Users/Lee/Source/sample/child.js:3
setTimeout(()=>{
            ^
SyntaxError: Unexpected token )
    at exports.runInThisContext (vm.js:53:16)
    at Module._compile (module.js:411:25)
    at Object.Module._extensions..js (module.js:446:10)
    at Module.load (module.js:353:32)
    at Function.Module._load (module.js:308:12)
    at Function.Module.runMain (module.js:469:10)
    at startup (node.js:124:18)
    at node.js:882:3

But once I changed the code, I verified that on Mac OS X 10.11.2 I saw the spawn → wait ten seconds → exited behavior (both with and without socket.io commented out). I’ll see if I can spin up a Windows VM next.


#12

You must have an old version of node installed. The code is slightly newer. That syntax is a basic arrow function in es6. Versions of node previous to the merger back with io.js would need the harmony flag to make that work. I was running node 4.2.0 so I didn’t notice it. Sorry about that.


#13

Yeah, turns out I’m running a pretty old version of Node at the command line :laughing: I forgot that electron-prebuilt just used the environment’s Node. Still fiddling.


#14

Any progress on this @leedohm? Were you able to replicate my issue? Do you think we should still get @mark_hahn involved?


#15

Unfortunately I don’t have much more to contribute. I haven’t run electron by itself.

Maybe one more nugget of wisdom. I’ve had problems in the past with socket.io. There are several newer modules that are simpler and more reliable. I just replaced websockets altogether in my latest app. I’m using normal ajax in combination with server-sent-events (http://www.html5rocks.com/en/tutorials/eventsource/basics/). SSE is so simple I have no code in the browser. It is built-in. It is very fast and easy to program. I use the npm module sse-channel. Check it out.


#16

I have a lot invested in socket.io already at this point so swapping to something else would be a bit of a challenge. If you notice in the above post though, I don’t even initialize socket.io. All I had to do was try to require it and it breaks. The child script was nothing but a require statement and a timeout to prevent it from exiting immediately after the require.

I just can’t wrap my head around whats going on with it, with it giving no error or anything, it just dies.


#17

I’m still trying to get my Windows VM up and running. Sorry it is taking so long :frowning:


#18

You know that doing a require runs the code in the module, right?


#19

Indeed. I just wouldn’t think it would be doing a lot in this case until you started the socket.io server up using .listen() but maybe I’m wrong on that.


#20

So, just wanted to give you guys an update on something I found later on. I eventually got this to work. I’m not sure what combination of changes and black magic did it. I can get it to run in Windows except when using an asar. When using an asar it still breaks but I think that’s because it’s trying to spawn a child process that exists inside the asar and I don’t think that works if I understand the documentation correctly. Would you know any way around this?