Skip to content

Forked child process not detaching on windows #5146

Description

@filmerjarred

As far as I can tell the expected default behavior of a child process created with child_process.fork, is to be able to run independently of the process that spawned it once the parent dies.

//parent.js
var child_process = require("child_process");

var p = child_process.fork("child.js")
p.disconnect();
p.unref();

process.exit()
//child.js
setTimeout(function(){
    console.log(1);
}, 1000000);

So if parents.js is executed, child.js should remain as an orphaned process after the parent exits. This works on Linux, but not on Windows.

Tested on Ubuntu 14.04.3 LTS and Windows 8.1
Using Node v5.5.0 and v0.10.25 (both tested on each platform)

Activity

  1. added
    child_processIssues and PRs related to the child_process subsystem.
    windowsIssues and PRs related to the Windows platform.
    on Feb 9, 2016
  2. bnoordhuis commented on Feb 12, 2016

    @bnoordhuis
    Member

    As far as I can tell the expected default behavior of a child process created with child_process.fork, is to be able to run independently of the process that spawned it once the parent dies.

    The documentation indeed uses the word "independent" but the intent is convey that the processes are independent instances of the runtime, not that they're exempt from normal process control. /cc @nodejs/documentation - that should probably be cleared up.

    On Windows, the child processes that node spawns are part of the same process group unless { detached: true } is passed to child_process.spawn().

    In detached mode, the child process is created with the CREATE_NEW_PROCESS_GROUP and DETACHED_PROCESS flags set. See the documentation for the detached option for a list of caveats.

  3. Knighton910 commented on Feb 12, 2016

    @Knighton910

    @nodejs/documentation - that should probably be cleared up.

    I'm on it @bnoordhuis
    I'll have it done in the following days, & I'll consult @chrisdickinson before it goes into queue for a PR

  4. filmerjarred commented on Feb 14, 2016

    @filmerjarred
    Author

    Yeah, I suspected that was the case re detached. Upon further testing I've found that the reason passing detached into the fork options wasn't working for me originally is that

    childProcess.spawn("node", ["child.js"], {detached:true, stdio:[0, 1, 2, 'ipc']});
    or
    childProcess.fork("child.js", {detached:true})
    

    doesn't work on windows (the child process just doesn't spawn), whereas

    childProcess.spawn("node", ["child.js"], {detached:true, stdio:['pipe', 'pipe', 'pipe', 'ipc']});
    or
    childProcess.fork("child.js", {detached:true, silent:true});
    

    works fine. My guess would be that spawning a child process with inherited fd's and the detached flags crashes it?

  5. bnoordhuis commented on Feb 15, 2016

    @bnoordhuis
    Member

    I'm going to defer to @nodejs/platform-windows for that. The tests we have for that particular child_process+stdio pattern are disabled on Windows but I don't know the details.

  6. eljefedelrodeodeljefe commented on Feb 18, 2016

    @eljefedelrodeodeljefe
    Contributor

    I am currently researching on this. The standard behaviour on unices is only to do setsid() but not ignoring SIGHUP. Meaning it terminates on closing the tty session. First, we could clear this up in docs, but anyhow we don't provide to possibility to opt-in for ignoring SIGHUP. That might be worth a PR to libuvor implementing it in js, given that the programmer is expecting orphaned processes. What would you think @bnoordhuis ?

    I am researching this on windows, but isn't the child_process automatically detached by default on windows threading implementation?

    At least there it's dispatching SIGHUP explicitly.

  7. bnoordhuis commented on Feb 18, 2016

    @bnoordhuis
    Member

    we don't provide to possibility to opt-in for ignoring SIGHUP

    You can install a handler for it like this:

    process.on('SIGHUP', () => {});  // ignore

    FWIW, I don't think it's a good idea to mix that with { detached: true } somehow. They're orthogonal concepts.

    isn't the child_process automatically detached by default on windows threading implementation?

    Depends on your definition of 'detached'. The Windows and POSIX process models are different enough that it's a bit of an apples vs. oranges comparison.

  8. eljefedelrodeodeljefe commented on Feb 18, 2016

    @eljefedelrodeodeljefe
    Contributor

    My point would be to make it very explicit by providing some kind of child_process.release() or {relase: true} option, like what I believe go has:

    process, err := os.StartProcess("/bin/sleep", []string{"/bib/sleep", "100"}, &attr)
    if err == nil {
    
        // It is not clear from docs, but Realease actually detaches the process
        err = process.Release();
        if err != nil {
            fmt.Println(err.Error())
       }
    } else {
        fmt.Println(err.Error())
    }

    Since there are a lot of SO questions and other discussions about this, that would ease it. Instead of using a state machine and a no-op.

    Example taken from here

  9. eljefedelrodeodeljefe commented on Feb 19, 2016

    @eljefedelrodeodeljefe
    Contributor

    @bnoordhuis tested the noop, and I believe it doesn't work:

    This will close the child process anyhow (Mac OS X).

    // child_detach_payload.js
    const cp = require('child_process')
    cp.fork("child_detach_payload.js", {detached:true})
    // child_detach_payload.js
    process.on('SIGHUP', () => {});  // ingore parents close event
    setInterval(function() {
      console.log('-> detached program doing work here');
    }, 1000)
  10. bnoordhuis commented on Feb 19, 2016

    @bnoordhuis
    Member

    You mean when you close the terminal? I think that's because of OS X-specific behavior where writing to the tty fails with EIO. Also, it's possible the stock terminal emulator hard-kills any processes.

  11. eljefedelrodeodeljefe commented on Feb 19, 2016

    @eljefedelrodeodeljefe
    Contributor

    Hmm. Interesting. Could reproduce on ubuntu though. I'll have a deeper look into the sources. Once I am through with osx and linux, I'll test on windows.

  12. jasnell commented on Jun 7, 2016

    @jasnell
    Member

    I believe this can be closed since #5330 landed. We can reopen this if that assumption is incorrect.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    child_processIssues and PRs related to the child_process subsystem.windowsIssues and PRs related to the Windows platform.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions