Skip to content
This repository
tag: v0.3.7
Fetching contributors…

Octocat-spinner-32-eaf2f5

Cannot retrieve contributors at this time

file 128 lines (104 sloc) 3.459 kb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127
// Copyright 2009 Ryan Dahl <ry@tinyclouds.org>
#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_
Something went wrong with that request. Please try again.