You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

147 lines
4.4 KiB

// Copyright Joyent, Inc. and other Node contributors.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to permit
// persons to whom the Software is furnished to do so, subject to the
// following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
// USE OR OTHER DEALINGS IN THE SOFTWARE.
#ifndef NODE_CHILD_PROCESS_H_
#define NODE_CHILD_PROCESS_H_
#include <node.h>
#include <node_object_wrap.h>
#include <v8.h>
#include <ev.h>
#ifdef __MINGW32__
# include <platform_win32.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
// wrapped up in a more friendly EventEmitter with streams for each of the
// pipes.
//
// When the child process exits (when the parent receives SIGCHLD) the
// callback child.onexit will be called.
namespace node {
class ChildProcess : ObjectWrap {
public:
static void Initialize(v8::Handle<v8::Object> target);
protected:
static v8::Handle<v8::Value> New(const v8::Arguments& args);
static v8::Handle<v8::Value> Spawn(const v8::Arguments& args);
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,
// stdout, and stderr of the subprocess. stdin is writable; the other two
// are readable.
// The user of this class has responsibility to close these pipes after
// the child process exits.
int Spawn(const char *file,
char *const argv[],
const char *cwd,
char **env,
int stdio_fds[3],
int custom_fds[3],
bool do_setsid,
int custom_uid,
char *custom_uname,
int custom_gid,
char *custom_gname);
// Simple syscall wrapper. Does not disable the watcher. onexit will be
// called still.
int Kill(int sig);
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) {
ChildProcess *child = static_cast<ChildProcess*>(watcher->data);
assert(revents == EV_CHILD);
assert(child->pid_ == watcher->rpid);
assert(&child->child_watcher_ == watcher);
child->OnExit(watcher->rstatus);
}
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_P_ 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
#endif // NODE_CHILD_PROCESS_H_