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

Commit

Permalink
Child processes
Browse files Browse the repository at this point in the history
  • Loading branch information
piscisaureus committed Dec 20, 2010
1 parent 0b96c5b commit 0a2f1cb
Show file tree
Hide file tree
Showing 5 changed files with 947 additions and 9 deletions.
23 changes: 17 additions & 6 deletions TODO.win32
Expand Up @@ -8,12 +8,23 @@
E.g. getaddrinfo() is ansi-only; GetAddrInfoW is utf16-only. Can we get utf16 straight out of v8?
Are unix sockets similar to windows named pipes? If so, should they be supported? -> currently: no. Complication: they block.

- Child processes
Should not be too hard using CreatePipe, CreateProcessW and GetExitCodeProcess.
Hooking up a child process to a file handle can be done; hooking up to a normal socket won't work;
we'd need some sort of pump() mechanism.
Waiting for the child to exit is tricky, probably would require a wait thread to wait for the child, then ev_async notify.
How can we distinguish between the exit code and exception number after calling GetExitCodeProcess?
- Child process issues
* Communication between parent and child is slow; it uses a socketpair
where a pipe would be much faster. Replace it by a pipe when there
is a libev backend that supports waiting for a pipe.
* When a child process spawns the pid is not available straightaway.
On linux the pid is available immediately because fork() doesn't
block; on windows a libeio thread is used to call CreateProcess.
So this can't really be fixed, but it could be worked around by adding a
'spawn' or 'pid' method.
* kill() doesn't work when the pid is not available yet. All the plumbing
is there to make it work, but lib/child_process.js just doesn't call
ChildProcess::Kill() as long as the pid is not known.
* passing socket custom_fds is not supported
* child_process.exec() only works on systems with msys installed.
It's because it relies on the 'sh' shell. The default windows shell
is 'cmd' and it works a little differently. Maybe add an option to
specify the shell to exec()?

- Stdio (make TTY's / repl / readline work)
This will be hard: there is no ANSI escape code support in windows.
Expand Down
4 changes: 4 additions & 0 deletions src/node_child_process.cc
@@ -1,3 +1,7 @@
#ifdef __MINGW32__
# include <node_child_process_win32.cc>
#endif

#ifdef __POSIX__

// Copyright 2009 Ryan Dahl <ry@tinyclouds.org>
Expand Down
50 changes: 49 additions & 1 deletion src/node_child_process.h
Expand Up @@ -7,6 +7,10 @@
#include <v8.h>
#include <ev.h>

#ifdef __MINGW32__
# include <windows.h> // HANDLE type
#endif

// ChildProcess is a thin wrapper around ev_child. It has the extra
// functionality that it can spawn a child process with pipes connected to
// its stdin, stdout, stderr. This class is not meant to be exposed to but
Expand All @@ -28,13 +32,25 @@ class ChildProcess : ObjectWrap {
static v8::Handle<v8::Value> Kill(const v8::Arguments& args);

ChildProcess() : ObjectWrap() {
#ifdef __POSIX__
ev_init(&child_watcher_, ChildProcess::on_chld);
child_watcher_.data = this;
#endif // __POSIX__

pid_ = -1;

#ifdef __MINGW32__
InitializeCriticalSection(&info_lock_);
kill_me_ = false;
did_start_ = false;
exit_signal_ = 0;
#endif // __MINGW32__
}

~ChildProcess() {
#ifdef __POSIX__
Stop();
#endif // __POSIX__
}

// Returns 0 on success. stdio_fds will contain file desciptors for stdin,
Expand All @@ -48,8 +64,10 @@ class ChildProcess : ObjectWrap {
// called still.
int Kill(int sig);

private:
private:
void OnExit(int code);

#ifdef __POSIX__ // Shouldn't this just move to node_child_process.cc?
void Stop(void);

static void on_chld(EV_P_ ev_child *watcher, int revents) {
Expand All @@ -62,6 +80,36 @@ class ChildProcess : ObjectWrap {

ev_child child_watcher_;
pid_t pid_;
#endif // __POSIX__

#ifdef __MINGW32__
static int do_spawn(eio_req *req);
static int after_spawn(eio_req *req);
static void watch(ChildProcess *child);
static void CALLBACK watch_wait_callback(void *data, BOOLEAN didTimeout);
static void notify_spawn_failure(ChildProcess *child);
static void notify_exit(ev_async *ev, int revent);
static int do_kill(ChildProcess *child, int sig);static void close_stdio_handles(ChildProcess *child);

int pid_;
int exit_signal_;

WCHAR *application_;
WCHAR *arguments_;
WCHAR *env_win_;
WCHAR *cwd_;
const WCHAR *path_;
const WCHAR *path_ext_;

HANDLE stdio_handles_[3];
bool got_custom_fds_[3];

CRITICAL_SECTION info_lock_;
bool did_start_;
bool kill_me_;
HANDLE wait_handle_;
HANDLE process_handle_;
#endif // __MINGW32__
};

} // namespace node
Expand Down

0 comments on commit 0a2f1cb

Please sign in to comment.