Permalink
Browse files

Child processes

  • Loading branch information...
1 parent 0b96c5b commit 0a2f1cb334e1633f0687bbd3442d433599dc08b0 @piscisaureus piscisaureus committed Dec 3, 2010
Showing with 947 additions and 9 deletions.
  1. +17 −6 TODO.win32
  2. +4 −0 src/node_child_process.cc
  3. +49 −1 src/node_child_process.h
  4. +877 −0 src/node_child_process_win32.cc
  5. +0 −2 src/node_extensions.h
View
@@ -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.
@@ -1,3 +1,7 @@
+#ifdef __MINGW32__
+# include <node_child_process_win32.cc>
+#endif
+
#ifdef __POSIX__
// Copyright 2009 Ryan Dahl <ry@tinyclouds.org>
View
@@ -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
@@ -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,
@@ -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) {
@@ -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
Oops, something went wrong.

0 comments on commit 0a2f1cb

Please sign in to comment.