1 // Copyright Joyent, Inc. and other Node contributors.
3 // Permission is hereby granted, free of charge, to any person obtaining a
4 // copy of this software and associated documentation files (the
5 // "Software"), to deal in the Software without restriction, including
6 // without limitation the rights to use, copy, modify, merge, publish,
7 // distribute, sublicense, and/or sell copies of the Software, and to permit
8 // persons to whom the Software is furnished to do so, subject to the
9 // following conditions:
11 // The above copyright notice and this permission notice shall be included
12 // in all copies or substantial portions of the Software.
14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
17 // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
18 // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19 // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
20 // USE OR OTHER DEALINGS IN THE SOFTWARE.
25 #include <node_dtrace.h>
32 #include <limits.h> /* PATH_MAX */
36 #include <sys/types.h>
37 #include <unistd.h> /* setuid, getuid */
40 # include <platform_win32.h> /* winapi_perror() */
41 # include <platform_win32_winsock.h> /* wsa_init() */
45 # include <dlfcn.h> /* dlopen(), dlsym() */
46 # include <pwd.h> /* getpwnam() */
47 # include <grp.h> /* getgrnam() */
51 #include <node_buffer.h>
52 #include <node_io_watcher.h>
54 #include <node_events.h>
55 #include <node_cares.h>
56 #include <node_file.h>
59 # include <node_idle_watcher.h>
61 #include <node_http_parser.h>
62 #include <node_signal_watcher.h>
63 #include <node_stat_watcher.h>
64 #include <node_timer.h>
65 #include <node_child_process.h>
66 #include <node_constants.h>
67 #include <node_stdio.h>
68 #include <node_javascript.h>
69 #include <node_version.h>
70 #include <node_string.h>
72 # include <node_crypto.h>
74 #include <node_script.h>
76 #define ARRAY_SIZE(a) (sizeof(a) / sizeof(*(a)))
81 # include <crt_externs.h>
82 # define environ (*_NSGetEnviron())
84 extern char **environ;
89 static Persistent<Object> process;
91 static Persistent<String> errno_symbol;
92 static Persistent<String> syscall_symbol;
93 static Persistent<String> errpath_symbol;
94 static Persistent<String> code_symbol;
96 static Persistent<String> rss_symbol;
97 static Persistent<String> vsize_symbol;
98 static Persistent<String> heap_total_symbol;
99 static Persistent<String> heap_used_symbol;
101 static Persistent<String> listeners_symbol;
102 static Persistent<String> uncaught_exception_symbol;
103 static Persistent<String> emit_symbol;
106 static char *eval_string = NULL;
107 static int option_end_index = 0;
108 static bool use_debug_agent = false;
109 static bool debug_wait_connect = false;
110 static int debug_port=5858;
111 static int max_stack_size = 0;
113 static ev_check check_tick_watcher;
114 static ev_prepare prepare_tick_watcher;
115 static ev_idle tick_spinner;
116 static bool need_tick_cb;
117 static Persistent<String> tick_callback_sym;
119 static ev_async eio_want_poll_notifier;
120 static ev_async eio_done_poll_notifier;
121 static ev_idle eio_poller;
123 // Buffer for getpwnam_r(), getgrpam_r() and other misc callers; keep this
124 // scoped at file-level rather than method-level to avoid excess stack usage.
125 static char getbuf[PATH_MAX + 1];
127 // We need to notify V8 when we're idle so that it can run the garbage
128 // collector. The interface to this is V8::IdleNotification(). It returns
129 // true if the heap hasn't be fully compacted, and needs to be run again.
130 // Returning false means that it doesn't have anymore work to do.
132 // A rather convoluted algorithm has been devised to determine when Node is
133 // idle. You'll have to figure it out for yourself.
134 static ev_check gc_check;
135 static ev_idle gc_idle;
136 static ev_timer gc_timer;
140 #define FAST_TICK 0.7
141 #define GC_WAIT_TIME 5.
142 #define RPM_SAMPLES 100
143 #define TICK_TIME(n) tick_times[(tick_time_head - (n)) % RPM_SAMPLES]
144 static ev_tstamp tick_times[RPM_SAMPLES];
145 static int tick_time_head;
147 static void StartGCTimer () {
148 if (!ev_is_active(&gc_timer)) {
149 ev_timer_start(EV_DEFAULT_UC_ &gc_timer);
150 ev_unref(EV_DEFAULT_UC);
154 static void StopGCTimer () {
155 if (ev_is_active(&gc_timer)) {
156 ev_ref(EV_DEFAULT_UC);
157 ev_timer_stop(EV_DEFAULT_UC_ &gc_timer);
161 static void Idle(EV_P_ ev_idle *watcher, int revents) {
162 assert(watcher == &gc_idle);
163 assert(revents == EV_IDLE);
165 //fprintf(stderr, "idle\n");
167 if (V8::IdleNotification()) {
168 ev_idle_stop(EV_A_ watcher);
174 // Called directly after every call to select() (or epoll, or whatever)
175 static void Check(EV_P_ ev_check *watcher, int revents) {
176 assert(watcher == &gc_check);
177 assert(revents == EV_CHECK);
179 tick_times[tick_time_head] = ev_now(EV_DEFAULT_UC);
180 tick_time_head = (tick_time_head + 1) % RPM_SAMPLES;
184 for (int i = 0; i < (int)(GC_WAIT_TIME/FAST_TICK); i++) {
185 double d = TICK_TIME(i+1) - TICK_TIME(i+2);
186 //printf("d = %f\n", d);
187 // If in the last 5 ticks the difference between
188 // ticks was less than 0.7 seconds, then continue.
195 // Otherwise start the gc!
197 //fprintf(stderr, "start idle 2\n");
198 ev_idle_start(EV_A_ &gc_idle);
202 static Handle<Value> NeedTickCallback(const Arguments& args) {
205 // TODO: this tick_spinner shouldn't be necessary. An ev_prepare should be
206 // sufficent, the problem is only in the case of the very last "tick" -
207 // there is nothing left to do in the event loop and libev will exit. The
208 // ev_prepare callback isn't called before exiting. Thus we start this
209 // tick_spinner to keep the event loop alive long enough to handle it.
210 ev_idle_start(EV_DEFAULT_UC_ &tick_spinner);
215 static void Spin(EV_P_ ev_idle *watcher, int revents) {
216 assert(watcher == &tick_spinner);
217 assert(revents == EV_IDLE);
221 static void Tick(void) {
222 // Avoid entering a V8 scope.
223 if (!need_tick_cb) return;
225 need_tick_cb = false;
226 ev_idle_stop(EV_DEFAULT_UC_ &tick_spinner);
230 if (tick_callback_sym.IsEmpty()) {
231 // Lazily set the symbol
233 Persistent<String>::New(String::NewSymbol("_tickCallback"));
236 Local<Value> cb_v = process->Get(tick_callback_sym);
237 if (!cb_v->IsFunction()) return;
238 Local<Function> cb = Local<Function>::Cast(cb_v);
242 cb->Call(process, 0, NULL);
244 if (try_catch.HasCaught()) {
245 FatalException(try_catch);
250 static void PrepareTick(EV_P_ ev_prepare *watcher, int revents) {
251 assert(watcher == &prepare_tick_watcher);
252 assert(revents == EV_PREPARE);
257 static void CheckTick(EV_P_ ev_check *watcher, int revents) {
258 assert(watcher == &check_tick_watcher);
259 assert(revents == EV_CHECK);
264 static void DoPoll(EV_P_ ev_idle *watcher, int revents) {
265 assert(watcher == &eio_poller);
266 assert(revents == EV_IDLE);
268 //printf("eio_poller\n");
270 if (eio_poll() != -1) {
271 //printf("eio_poller stop\n");
272 ev_idle_stop(EV_DEFAULT_UC_ watcher);
277 // Called from the main thread.
278 static void WantPollNotifier(EV_P_ ev_async *watcher, int revents) {
279 assert(watcher == &eio_want_poll_notifier);
280 assert(revents == EV_ASYNC);
282 //printf("want poll notifier\n");
284 if (eio_poll() == -1) {
285 //printf("eio_poller start\n");
286 ev_idle_start(EV_DEFAULT_UC_ &eio_poller);
291 static void DonePollNotifier(EV_P_ ev_async *watcher, int revents) {
292 assert(watcher == &eio_done_poll_notifier);
293 assert(revents == EV_ASYNC);
295 //printf("done poll notifier\n");
297 if (eio_poll() != -1) {
298 //printf("eio_poller stop\n");
299 ev_idle_stop(EV_DEFAULT_UC_ &eio_poller);
304 // EIOWantPoll() is called from the EIO thread pool each time an EIO
305 // request (that is, one of the node.fs.* functions) has completed.
306 static void EIOWantPoll(void) {
307 // Signal the main thread that eio_poll need to be processed.
308 ev_async_send(EV_DEFAULT_UC_ &eio_want_poll_notifier);
312 static void EIODonePoll(void) {
313 // Signal the main thread that we should stop calling eio_poll().
314 // from the idle watcher.
315 ev_async_send(EV_DEFAULT_UC_ &eio_done_poll_notifier);
319 static inline const char *errno_string(int errorno) {
320 #define ERRNO_CASE(e) case e: return #e;
328 ERRNO_CASE(EADDRINUSE);
332 ERRNO_CASE(EADDRNOTAVAIL);
336 ERRNO_CASE(EAFNOSUPPORT);
344 # if EAGAIN != EWOULDBLOCK
345 ERRNO_CASE(EWOULDBLOCK);
350 ERRNO_CASE(EALREADY);
366 ERRNO_CASE(ECANCELED);
374 ERRNO_CASE(ECONNABORTED);
378 ERRNO_CASE(ECONNREFUSED);
382 ERRNO_CASE(ECONNRESET);
390 ERRNO_CASE(EDESTADDRREQ);
414 ERRNO_CASE(EHOSTUNREACH);
426 ERRNO_CASE(EINPROGRESS);
462 ERRNO_CASE(EMSGSIZE);
466 ERRNO_CASE(EMULTIHOP);
470 ERRNO_CASE(ENAMETOOLONG);
474 ERRNO_CASE(ENETDOWN);
478 ERRNO_CASE(ENETRESET);
482 ERRNO_CASE(ENETUNREACH);
514 # if ENOLINK != ENOLCK
528 ERRNO_CASE(ENOPROTOOPT);
548 ERRNO_CASE(ENOTCONN);
556 ERRNO_CASE(ENOTEMPTY);
560 ERRNO_CASE(ENOTSOCK);
567 ERRNO_CASE(EOPNOTSUPP);
581 ERRNO_CASE(EOVERFLOW);
596 #ifdef EPROTONOSUPPORT
597 ERRNO_CASE(EPROTONOSUPPORT);
601 ERRNO_CASE(EPROTOTYPE);
629 ERRNO_CASE(ETIMEDOUT);
641 ERRNO_CASE(WSAEINTR);
645 ERRNO_CASE(WSAEBADF);
649 ERRNO_CASE(WSAEACCES);
653 ERRNO_CASE(WSAEFAULT);
657 ERRNO_CASE(WSAEINVAL);
661 ERRNO_CASE(WSAEMFILE);
664 #ifdef WSAEWOULDBLOCK
665 ERRNO_CASE(WSAEWOULDBLOCK);
668 #ifdef WSAEINPROGRESS
669 ERRNO_CASE(WSAEINPROGRESS);
673 ERRNO_CASE(WSAEALREADY);
677 ERRNO_CASE(WSAENOTSOCK);
680 #ifdef WSAEDESTADDRREQ
681 ERRNO_CASE(WSAEDESTADDRREQ);
685 ERRNO_CASE(WSAEMSGSIZE);
689 ERRNO_CASE(WSAEPROTOTYPE);
692 #ifdef WSAENOPROTOOPT
693 ERRNO_CASE(WSAENOPROTOOPT);
696 #ifdef WSAEPROTONOSUPPORT
697 ERRNO_CASE(WSAEPROTONOSUPPORT);
700 #ifdef WSAESOCKTNOSUPPORT
701 ERRNO_CASE(WSAESOCKTNOSUPPORT);
705 ERRNO_CASE(WSAEOPNOTSUPP);
708 #ifdef WSAEPFNOSUPPORT
709 ERRNO_CASE(WSAEPFNOSUPPORT);
712 #ifdef WSAEAFNOSUPPORT
713 ERRNO_CASE(WSAEAFNOSUPPORT);
717 ERRNO_CASE(WSAEADDRINUSE);
720 #ifdef WSAEADDRNOTAVAIL
721 ERRNO_CASE(WSAEADDRNOTAVAIL);
725 ERRNO_CASE(WSAENETDOWN);
728 #ifdef WSAENETUNREACH
729 ERRNO_CASE(WSAENETUNREACH);
733 ERRNO_CASE(WSAENETRESET);
736 #ifdef WSAECONNABORTED
737 ERRNO_CASE(WSAECONNABORTED);
741 ERRNO_CASE(WSAECONNRESET);
745 ERRNO_CASE(WSAENOBUFS);
749 ERRNO_CASE(WSAEISCONN);
753 ERRNO_CASE(WSAENOTCONN);
757 ERRNO_CASE(WSAESHUTDOWN);
760 #ifdef WSAETOOMANYREFS
761 ERRNO_CASE(WSAETOOMANYREFS);
765 ERRNO_CASE(WSAETIMEDOUT);
768 #ifdef WSAECONNREFUSED
769 ERRNO_CASE(WSAECONNREFUSED);
773 ERRNO_CASE(WSAELOOP);
776 #ifdef WSAENAMETOOLONG
777 ERRNO_CASE(WSAENAMETOOLONG);
781 ERRNO_CASE(WSAEHOSTDOWN);
784 #ifdef WSAEHOSTUNREACH
785 ERRNO_CASE(WSAEHOSTUNREACH);
789 ERRNO_CASE(WSAENOTEMPTY);
793 ERRNO_CASE(WSAEPROCLIM);
797 ERRNO_CASE(WSAEUSERS);
801 ERRNO_CASE(WSAEDQUOT);
805 ERRNO_CASE(WSAESTALE);
809 ERRNO_CASE(WSAEREMOTE);
812 #ifdef WSASYSNOTREADY
813 ERRNO_CASE(WSASYSNOTREADY);
816 #ifdef WSAVERNOTSUPPORTED
817 ERRNO_CASE(WSAVERNOTSUPPORTED);
820 #ifdef WSANOTINITIALISED
821 ERRNO_CASE(WSANOTINITIALISED);
825 ERRNO_CASE(WSAEDISCON);
829 ERRNO_CASE(WSAENOMORE);
833 ERRNO_CASE(WSAECANCELLED);
836 #ifdef WSAEINVALIDPROCTABLE
837 ERRNO_CASE(WSAEINVALIDPROCTABLE);
840 #ifdef WSAEINVALIDPROVIDER
841 ERRNO_CASE(WSAEINVALIDPROVIDER);
844 #ifdef WSAEPROVIDERFAILEDINIT
845 ERRNO_CASE(WSAEPROVIDERFAILEDINIT);
848 #ifdef WSASYSCALLFAILURE
849 ERRNO_CASE(WSASYSCALLFAILURE);
852 #ifdef WSASERVICE_NOT_FOUND
853 ERRNO_CASE(WSASERVICE_NOT_FOUND);
856 #ifdef WSATYPE_NOT_FOUND
857 ERRNO_CASE(WSATYPE_NOT_FOUND);
861 ERRNO_CASE(WSA_E_NO_MORE);
864 #ifdef WSA_E_CANCELLED
865 ERRNO_CASE(WSA_E_CANCELLED);
872 const char *signo_string(int signo) {
873 #define SIGNO_CASE(e) case e: return #e;
901 # if SIGABRT != SIGIOT
945 SIGNO_CASE(SIGSTKFLT);
982 SIGNO_CASE(SIGVTALRM);
990 SIGNO_CASE(SIGWINCH);
998 # if SIGPOLL != SIGIO
1004 SIGNO_CASE(SIGLOST);
1008 # if SIGPWR != SIGLOST
1022 Local<Value> ErrnoException(int errorno,
1023 const char *syscall,
1027 Local<String> estring = String::NewSymbol(errno_string(errorno));
1030 msg = strerror(errorno);
1031 #else // __MINGW32__
1032 msg = winapi_strerror(errorno);
1035 Local<String> message = String::NewSymbol(msg);
1037 Local<String> cons1 = String::Concat(estring, String::NewSymbol(", "));
1038 Local<String> cons2 = String::Concat(cons1, message);
1040 if (errno_symbol.IsEmpty()) {
1041 syscall_symbol = NODE_PSYMBOL("syscall");
1042 errno_symbol = NODE_PSYMBOL("errno");
1043 errpath_symbol = NODE_PSYMBOL("path");
1044 code_symbol = NODE_PSYMBOL("code");
1048 Local<String> cons3 = String::Concat(cons2, String::NewSymbol(" '"));
1049 Local<String> cons4 = String::Concat(cons3, String::New(path));
1050 Local<String> cons5 = String::Concat(cons4, String::NewSymbol("'"));
1051 e = Exception::Error(cons5);
1053 e = Exception::Error(cons2);
1056 Local<Object> obj = e->ToObject();
1058 obj->Set(errno_symbol, Integer::New(errorno));
1059 obj->Set(code_symbol, estring);
1060 if (path) obj->Set(errpath_symbol, String::New(path));
1061 if (syscall) obj->Set(syscall_symbol, String::NewSymbol(syscall));
1066 Handle<Value> FromConstructorTemplate(Persistent<FunctionTemplate>& t,
1067 const Arguments& args) {
1070 const int argc = args.Length();
1071 Local<Value>* argv = new Local<Value>[argc];
1073 for (int i = 0; i < argc; ++i) {
1077 Local<Object> instance = t->GetFunction()->NewInstance(argc, argv);
1081 return scope.Close(instance);
1085 enum encoding ParseEncoding(Handle<Value> encoding_v, enum encoding _default) {
1088 if (!encoding_v->IsString()) return _default;
1090 String::Utf8Value encoding(encoding_v->ToString());
1092 if (strcasecmp(*encoding, "utf8") == 0) {
1094 } else if (strcasecmp(*encoding, "utf-8") == 0) {
1096 } else if (strcasecmp(*encoding, "ascii") == 0) {
1098 } else if (strcasecmp(*encoding, "base64") == 0) {
1100 } else if (strcasecmp(*encoding, "ucs2") == 0) {
1102 } else if (strcasecmp(*encoding, "ucs-2") == 0) {
1104 } else if (strcasecmp(*encoding, "binary") == 0) {
1106 } else if (strcasecmp(*encoding, "hex") == 0) {
1108 } else if (strcasecmp(*encoding, "raw") == 0) {
1109 fprintf(stderr, "'raw' (array of integers) has been removed. "
1112 } else if (strcasecmp(*encoding, "raws") == 0) {
1113 fprintf(stderr, "'raws' encoding has been renamed to 'binary'. "
1114 "Please update your code.\n");
1121 Local<Value> Encode(const void *buf, size_t len, enum encoding encoding) {
1124 if (!len) return scope.Close(String::Empty());
1126 if (encoding == BINARY) {
1127 const unsigned char *cbuf = static_cast<const unsigned char*>(buf);
1128 uint16_t * twobytebuf = new uint16_t[len];
1129 for (size_t i = 0; i < len; i++) {
1130 // XXX is the following line platform independent?
1131 twobytebuf[i] = cbuf[i];
1133 Local<String> chunk = String::New(twobytebuf, len);
1134 delete [] twobytebuf; // TODO use ExternalTwoByteString?
1135 return scope.Close(chunk);
1138 // utf8 or ascii encoding
1139 Local<String> chunk = String::New((const char*)buf, len);
1140 return scope.Close(chunk);
1143 // Returns -1 if the handle was not valid for decoding
1144 ssize_t DecodeBytes(v8::Handle<v8::Value> val, enum encoding encoding) {
1147 if (val->IsArray()) {
1148 fprintf(stderr, "'raw' encoding (array of integers) has been removed. "
1154 Local<String> str = val->ToString();
1156 if (encoding == UTF8) return str->Utf8Length();
1157 else if (encoding == UCS2) return str->Length() * 2;
1158 else if (encoding == HEX) return str->Length() / 2;
1160 return str->Length();
1164 # define MIN(a, b) ((a) < (b) ? (a) : (b))
1167 // Returns number of bytes written.
1168 ssize_t DecodeWrite(char *buf,
1170 v8::Handle<v8::Value> val,
1171 enum encoding encoding) {
1175 // A lot of improvement can be made here. See:
1176 // http://code.google.com/p/v8/issues/detail?id=270
1177 // http://groups.google.com/group/v8-dev/browse_thread/thread/dba28a81d9215291/ece2b50a3b4022c
1178 // http://groups.google.com/group/v8-users/browse_thread/thread/1f83b0ba1f0a611
1180 if (val->IsArray()) {
1181 fprintf(stderr, "'raw' encoding (array of integers) has been removed. "
1187 Local<String> str = val->ToString();
1189 if (encoding == UTF8) {
1190 str->WriteUtf8(buf, buflen, NULL, String::HINT_MANY_WRITES_EXPECTED);
1194 if (encoding == ASCII) {
1195 str->WriteAscii(buf, 0, buflen, String::HINT_MANY_WRITES_EXPECTED);
1199 // THIS IS AWFUL!!! FIXME
1201 assert(encoding == BINARY);
1203 uint16_t * twobytebuf = new uint16_t[buflen];
1205 str->Write(twobytebuf, 0, buflen, String::HINT_MANY_WRITES_EXPECTED);
1207 for (size_t i = 0; i < buflen; i++) {
1208 unsigned char *b = reinterpret_cast<unsigned char*>(&twobytebuf[i]);
1213 delete [] twobytebuf;
1219 void DisplayExceptionLine (TryCatch &try_catch) {
1222 Handle<Message> message = try_catch.Message();
1224 node::Stdio::DisableRawMode(STDIN_FILENO);
1225 fprintf(stderr, "\n");
1227 if (!message.IsEmpty()) {
1228 // Print (filename):(line number): (message).
1229 String::Utf8Value filename(message->GetScriptResourceName());
1230 const char* filename_string = *filename;
1231 int linenum = message->GetLineNumber();
1232 fprintf(stderr, "%s:%i\n", filename_string, linenum);
1233 // Print line of source code.
1234 String::Utf8Value sourceline(message->GetSourceLine());
1235 const char* sourceline_string = *sourceline;
1241 // Because of how CommonJS modules work, all scripts are wrapped with a
1242 // "function (function (exports, __filename, ...) {"
1243 // to provide script local variables.
1245 // When reporting errors on the first line of a script, this wrapper
1246 // function is leaked to the user. This HACK is to remove it. The length
1247 // of the wrapper is 62. That wrapper is defined in src/node.js
1249 // If that wrapper is ever changed, then this number also has to be
1250 // updated. Or - someone could clean this up so that the two peices
1251 // don't need to be changed.
1253 // Even better would be to get support into V8 for wrappers that
1254 // shouldn't be reported to users.
1255 int offset = linenum == 1 ? 62 : 0;
1257 fprintf(stderr, "%s\n", sourceline_string + offset);
1258 // Print wavy underline (GetUnderline is deprecated).
1259 int start = message->GetStartColumn();
1260 for (int i = offset; i < start; i++) {
1261 fprintf(stderr, " ");
1263 int end = message->GetEndColumn();
1264 for (int i = start; i < end; i++) {
1265 fprintf(stderr, "^");
1267 fprintf(stderr, "\n");
1272 static void ReportException(TryCatch &try_catch, bool show_line) {
1274 Handle<Message> message = try_catch.Message();
1276 if (show_line) DisplayExceptionLine(try_catch);
1278 String::Utf8Value trace(try_catch.StackTrace());
1280 if (trace.length() > 0) {
1281 fprintf(stderr, "%s\n", *trace);
1283 // this really only happens for RangeErrors, since they're the only
1284 // kind that won't have all this info in the trace.
1285 Local<Value> er = try_catch.Exception();
1286 String::Utf8Value msg(!er->IsObject() ? er->ToString()
1287 : er->ToObject()->Get(String::New("message"))->ToString());
1288 fprintf(stderr, "%s\n", *msg);
1294 // Executes a str within the current v8 context.
1295 Local<Value> ExecuteString(Handle<String> source, Handle<Value> filename) {
1299 Local<v8::Script> script = v8::Script::Compile(source, filename);
1300 if (script.IsEmpty()) {
1301 ReportException(try_catch, true);
1305 Local<Value> result = script->Run();
1306 if (result.IsEmpty()) {
1307 ReportException(try_catch, true);
1311 return scope.Close(result);
1315 static Handle<Value> Chdir(const Arguments& args) {
1318 if (args.Length() != 1 || !args[0]->IsString()) {
1319 return ThrowException(Exception::Error(String::New("Bad argument.")));
1322 String::Utf8Value path(args[0]->ToString());
1324 int r = chdir(*path);
1327 return ThrowException(Exception::Error(String::New(strerror(errno))));
1333 static Handle<Value> Cwd(const Arguments& args) {
1335 assert(args.Length() == 0);
1337 char *r = getcwd(getbuf, ARRAY_SIZE(getbuf) - 1);
1339 return ThrowException(Exception::Error(String::New(strerror(errno))));
1342 getbuf[ARRAY_SIZE(getbuf) - 1] = '\0';
1343 Local<String> cwd = String::New(r);
1345 return scope.Close(cwd);
1351 static Handle<Value> Umask(const Arguments& args){
1355 if(args.Length() < 1 || args[0]->IsUndefined()) {
1359 } else if(!args[0]->IsInt32() && !args[0]->IsString()) {
1360 return ThrowException(Exception::TypeError(
1361 String::New("argument must be an integer or octal string.")));
1365 if(args[0]->IsInt32()) {
1366 oct = args[0]->Uint32Value();
1369 String::Utf8Value str(args[0]);
1371 // Parse the octal string.
1372 for (int i = 0; i < str.length(); i++) {
1374 if (c > '7' || c < '0') {
1375 return ThrowException(Exception::TypeError(
1376 String::New("invalid octal string")));
1382 old = umask(static_cast<mode_t>(oct));
1385 return scope.Close(Uint32::New(old));
1389 static Handle<Value> GetUid(const Arguments& args) {
1391 assert(args.Length() == 0);
1393 return scope.Close(Integer::New(uid));
1396 static Handle<Value> GetGid(const Arguments& args) {
1398 assert(args.Length() == 0);
1400 return scope.Close(Integer::New(gid));
1404 static Handle<Value> SetGid(const Arguments& args) {
1407 if (args.Length() < 1) {
1408 return ThrowException(Exception::Error(
1409 String::New("setgid requires 1 argument")));
1414 if (args[0]->IsNumber()) {
1415 gid = args[0]->Int32Value();
1416 } else if (args[0]->IsString()) {
1417 String::Utf8Value grpnam(args[0]->ToString());
1418 struct group grp, *grpp = NULL;
1421 if ((err = getgrnam_r(*grpnam, &grp, getbuf, ARRAY_SIZE(getbuf), &grpp)) ||
1423 return ThrowException(ErrnoException(errno, "getgrnam_r"));
1428 return ThrowException(Exception::Error(
1429 String::New("setgid argument must be a number or a string")));
1433 if ((result = setgid(gid)) != 0) {
1434 return ThrowException(ErrnoException(errno, "setgid"));
1439 static Handle<Value> SetUid(const Arguments& args) {
1442 if (args.Length() < 1) {
1443 return ThrowException(Exception::Error(
1444 String::New("setuid requires 1 argument")));
1449 if (args[0]->IsNumber()) {
1450 uid = args[0]->Int32Value();
1451 } else if (args[0]->IsString()) {
1452 String::Utf8Value pwnam(args[0]->ToString());
1453 struct passwd pwd, *pwdp = NULL;
1456 if ((err = getpwnam_r(*pwnam, &pwd, getbuf, ARRAY_SIZE(getbuf), &pwdp)) ||
1458 return ThrowException(ErrnoException(errno, "getpwnam_r"));
1463 return ThrowException(Exception::Error(
1464 String::New("setuid argument must be a number or a string")));
1468 if ((result = setuid(uid)) != 0) {
1469 return ThrowException(ErrnoException(errno, "setuid"));
1477 v8::Handle<v8::Value> Exit(const v8::Arguments& args) {
1479 exit(args[0]->IntegerValue());
1484 static void CheckStatus(EV_P_ ev_timer *watcher, int revents) {
1485 assert(watcher == &gc_timer);
1486 assert(revents == EV_TIMEOUT);
1490 if (!ev_is_active(&gc_idle) && Platform::GetMemory(&rss, &vsize) == 0) {
1491 if (rss > 1024*1024*128) {
1492 // larger than 128 megs, just start the idle watcher
1493 ev_idle_start(EV_A_ &gc_idle);
1498 double d = ev_now(EV_DEFAULT_UC) - TICK_TIME(3);
1500 //printfb("timer d = %f\n", d);
1502 if (d >= GC_WAIT_TIME - 1.) {
1503 //fprintf(stderr, "start idle\n");
1504 ev_idle_start(EV_A_ &gc_idle);
1508 static Handle<Value> Uptime(const Arguments& args) {
1510 assert(args.Length() == 0);
1512 double uptime = Platform::GetUptime(true);
1518 return scope.Close(Number::New(uptime));
1521 v8::Handle<v8::Value> MemoryUsage(const v8::Arguments& args) {
1523 assert(args.Length() == 0);
1527 int r = Platform::GetMemory(&rss, &vsize);
1530 return ThrowException(Exception::Error(String::New(strerror(errno))));
1533 Local<Object> info = Object::New();
1535 if (rss_symbol.IsEmpty()) {
1536 rss_symbol = NODE_PSYMBOL("rss");
1537 vsize_symbol = NODE_PSYMBOL("vsize");
1538 heap_total_symbol = NODE_PSYMBOL("heapTotal");
1539 heap_used_symbol = NODE_PSYMBOL("heapUsed");
1542 info->Set(rss_symbol, Integer::NewFromUnsigned(rss));
1543 info->Set(vsize_symbol, Integer::NewFromUnsigned(vsize));
1546 HeapStatistics v8_heap_stats;
1547 V8::GetHeapStatistics(&v8_heap_stats);
1548 info->Set(heap_total_symbol,
1549 Integer::NewFromUnsigned(v8_heap_stats.total_heap_size()));
1550 info->Set(heap_used_symbol,
1551 Integer::NewFromUnsigned(v8_heap_stats.used_heap_size()));
1553 return scope.Close(info);
1559 Handle<Value> Kill(const Arguments& args) {
1562 if (args.Length() != 2) {
1563 return ThrowException(Exception::Error(String::New("Bad argument.")));
1566 pid_t pid = args[0]->IntegerValue();
1567 int sig = args[1]->Int32Value();
1568 int r = kill(pid, sig);
1570 if (r != 0) return ThrowException(ErrnoException(errno, "kill"));
1576 typedef void (*extInit)(Handle<Object> exports);
1578 // DLOpen is node.dlopen(). Used to load 'module.node' dynamically shared
1580 Handle<Value> DLOpen(const v8::Arguments& args) {
1583 if (args.Length() < 2) return Undefined();
1585 String::Utf8Value filename(args[0]->ToString()); // Cast
1586 Local<Object> target = args[1]->ToObject(); // Cast
1588 // Actually call dlopen().
1589 // FIXME: This is a blocking function and should be called asynchronously!
1590 // This function should be moved to file.cc and use libeio to make this
1592 void *handle = dlopen(*filename, RTLD_LAZY);
1595 if (handle == NULL) {
1596 Local<Value> exception = Exception::Error(String::New(dlerror()));
1597 return ThrowException(exception);
1600 String::Utf8Value symbol(args[0]->ToString());
1601 char *symstr = NULL;
1603 char *sym = *symbol;
1604 char *p = strrchr(sym, '/');
1609 p = strrchr(sym, '.');
1614 size_t slen = strlen(sym);
1615 symstr = static_cast<char*>(calloc(1, slen + sizeof("_module") + 1));
1616 memcpy(symstr, sym, slen);
1617 memcpy(symstr+slen, "_module", sizeof("_module") + 1);
1620 // Get the init() function from the dynamically shared object.
1621 node_module_struct *mod = static_cast<node_module_struct *>(dlsym(handle, symstr));
1623 // Error out if not found.
1625 /* Start Compatibility hack: Remove once everyone is using NODE_MODULE macro */
1626 node_module_struct compat_mod;
1628 mod->version = NODE_MODULE_VERSION;
1630 void *init_handle = dlsym(handle, "init");
1631 if (init_handle == NULL) {
1633 Local<Value> exception =
1634 Exception::Error(String::New("No module symbol found in module."));
1635 return ThrowException(exception);
1637 mod->register_func = (extInit)(init_handle);
1638 /* End Compatibility hack */
1641 if (mod->version != NODE_MODULE_VERSION) {
1642 Local<Value> exception =
1643 Exception::Error(String::New("Module version mismatch, refusing to load."));
1644 return ThrowException(exception);
1647 // Execute the C++ module
1648 mod->register_func(target);
1650 // Tell coverity that 'handle' should not be freed when we return.
1651 // coverity[leaked_storage]
1658 // TODO remove me before 0.4
1659 Handle<Value> Compile(const Arguments& args) {
1663 if (args.Length() < 2) {
1664 return ThrowException(Exception::TypeError(
1665 String::New("needs two arguments.")));
1668 static bool shown_error_message = false;
1670 if (!shown_error_message) {
1671 shown_error_message = true;
1672 fprintf(stderr, "(node) process.compile should not be used. "
1673 "Use require('vm').runInThisContext instead.\n");
1676 Local<String> source = args[0]->ToString();
1677 Local<String> filename = args[1]->ToString();
1681 Local<v8::Script> script = v8::Script::Compile(source, filename);
1682 if (try_catch.HasCaught()) {
1683 // Hack because I can't get a proper stacktrace on SyntaxError
1684 ReportException(try_catch, true);
1688 Local<Value> result = script->Run();
1689 if (try_catch.HasCaught()) {
1690 ReportException(try_catch, false);
1694 return scope.Close(result);
1697 static void OnFatalError(const char* location, const char* message) {
1699 fprintf(stderr, "FATAL ERROR: %s %s\n", location, message);
1701 fprintf(stderr, "FATAL ERROR: %s\n", message);
1706 static int uncaught_exception_counter = 0;
1708 void FatalException(TryCatch &try_catch) {
1711 // Check if uncaught_exception_counter indicates a recursion
1712 if (uncaught_exception_counter > 0) {
1713 ReportException(try_catch, true);
1717 if (listeners_symbol.IsEmpty()) {
1718 listeners_symbol = NODE_PSYMBOL("listeners");
1719 uncaught_exception_symbol = NODE_PSYMBOL("uncaughtException");
1720 emit_symbol = NODE_PSYMBOL("emit");
1723 Local<Value> listeners_v = process->Get(listeners_symbol);
1724 assert(listeners_v->IsFunction());
1726 Local<Function> listeners = Local<Function>::Cast(listeners_v);
1728 Local<String> uncaught_exception_symbol_l = Local<String>::New(uncaught_exception_symbol);
1729 Local<Value> argv[1] = { uncaught_exception_symbol_l };
1730 Local<Value> ret = listeners->Call(process, 1, argv);
1732 assert(ret->IsArray());
1734 Local<Array> listener_array = Local<Array>::Cast(ret);
1736 uint32_t length = listener_array->Length();
1737 // Report and exit if process has no "uncaughtException" listener
1739 ReportException(try_catch, true);
1743 // Otherwise fire the process "uncaughtException" event
1744 Local<Value> emit_v = process->Get(emit_symbol);
1745 assert(emit_v->IsFunction());
1747 Local<Function> emit = Local<Function>::Cast(emit_v);
1749 Local<Value> error = try_catch.Exception();
1750 Local<Value> event_argv[2] = { uncaught_exception_symbol_l, error };
1752 uncaught_exception_counter++;
1753 emit->Call(process, 2, event_argv);
1754 // Decrement so we know if the next exception is a recursion or not
1755 uncaught_exception_counter--;
1759 static ev_async debug_watcher;
1761 static void DebugMessageCallback(EV_P_ ev_async *watcher, int revents) {
1763 assert(watcher == &debug_watcher);
1764 assert(revents == EV_ASYNC);
1765 Debug::ProcessDebugMessages();
1768 static void DebugMessageDispatch(void) {
1769 // This function is called from V8's debug thread when a debug TCP client
1770 // has sent a message.
1772 // Send a signal to our main thread saying that it should enter V8 to
1773 // handle the message.
1774 ev_async_send(EV_DEFAULT_UC_ &debug_watcher);
1777 static void DebugBreakMessageHandler(const Debug::Message& message) {
1778 // do nothing with debug messages.
1779 // The message handler will get changed by DebuggerAgent::CreateSession in
1780 // debug-agent.cc of v8/src when a new session is created
1784 Persistent<Object> binding_cache;
1786 static Handle<Value> Binding(const Arguments& args) {
1789 Local<String> module = args[0]->ToString();
1790 String::Utf8Value module_v(module);
1791 node_module_struct* modp;
1793 if (binding_cache.IsEmpty()) {
1794 binding_cache = Persistent<Object>::New(Object::New());
1797 Local<Object> exports;
1799 if (binding_cache->Has(module)) {
1800 exports = binding_cache->Get(module)->ToObject();
1802 } else if ((modp = get_builtin_module(*module_v)) != NULL) {
1803 exports = Object::New();
1804 modp->register_func(exports);
1805 binding_cache->Set(module, exports);
1807 } else if (!strcmp(*module_v, "constants")) {
1808 exports = Object::New();
1809 DefineConstants(exports);
1810 binding_cache->Set(module, exports);
1812 } else if (!strcmp(*module_v, "io_watcher")) {
1813 exports = Object::New();
1814 IOWatcher::Initialize(exports);
1815 binding_cache->Set(module, exports);
1817 } else if (!strcmp(*module_v, "timer")) {
1818 exports = Object::New();
1819 Timer::Initialize(exports);
1820 binding_cache->Set(module, exports);
1822 } else if (!strcmp(*module_v, "natives")) {
1823 exports = Object::New();
1824 DefineJavaScript(exports);
1825 binding_cache->Set(module, exports);
1829 return ThrowException(Exception::Error(String::New("No such module")));
1832 return scope.Close(exports);
1836 static Handle<Value> ProcessTitleGetter(Local<String> property,
1837 const AccessorInfo& info) {
1840 const char *s = Platform::GetProcessTitle(&len);
1841 return scope.Close(s ? String::New(s, len) : String::Empty());
1845 static void ProcessTitleSetter(Local<String> property,
1847 const AccessorInfo& info) {
1849 String::Utf8Value title(value->ToString());
1850 Platform::SetProcessTitle(*title);
1854 static Handle<Value> EnvGetter(Local<String> property,
1855 const AccessorInfo& info) {
1856 String::Utf8Value key(property);
1857 const char* val = getenv(*key);
1860 return scope.Close(String::New(val));
1866 static bool ENV_warning = false;
1867 static Handle<Value> EnvGetterWarn(Local<String> property,
1868 const AccessorInfo& info) {
1871 fprintf(stderr, "(node) Use process.env instead of process.ENV\r\n");
1873 return EnvGetter(property, info);
1877 static Handle<Value> EnvSetter(Local<String> property,
1879 const AccessorInfo& info) {
1880 String::Utf8Value key(property);
1881 String::Utf8Value val(value);
1883 setenv(*key, *val, 1);
1891 static Handle<Integer> EnvQuery(Local<String> property,
1892 const AccessorInfo& info) {
1893 String::Utf8Value key(property);
1896 return scope.Close(Integer::New(None));
1898 return Handle<Integer>();
1902 static Handle<Boolean> EnvDeleter(Local<String> property,
1903 const AccessorInfo& info) {
1904 String::Utf8Value key(property);
1907 unsetenv(*key); // prototyped as `void unsetenv(const char*)` on some platforms
1909 NO_IMPL_MSG(unsetenv)
1917 static Handle<Array> EnvEnumerator(const AccessorInfo& info) {
1921 while (environ[size]) size++;
1923 Local<Array> env = Array::New(size);
1925 for (int i = 0; i < size; ++i) {
1926 const char* var = environ[i];
1927 const char* s = strchr(var, '=');
1928 const int length = s ? s - var : strlen(var);
1929 env->Set(i, String::New(var, length));
1932 return scope.Close(env);
1936 static void Load(int argc, char *argv[]) {
1941 Local<FunctionTemplate> process_template = FunctionTemplate::New();
1942 node::EventEmitter::Initialize(process_template);
1944 process = Persistent<Object>::New(process_template->GetFunction()->NewInstance());
1947 process->SetAccessor(String::New("title"),
1949 ProcessTitleSetter);
1952 process->Set(String::NewSymbol("version"), String::New(NODE_VERSION));
1954 // process.installPrefix
1955 process->Set(String::NewSymbol("installPrefix"), String::New(NODE_PREFIX));
1957 Local<Object> versions = Object::New();
1959 process->Set(String::NewSymbol("versions"), versions);
1960 // +1 to get rid of the leading 'v'
1961 versions->Set(String::NewSymbol("node"), String::New(NODE_VERSION+1));
1962 versions->Set(String::NewSymbol("v8"), String::New(V8::GetVersion()));
1963 versions->Set(String::NewSymbol("ares"), String::New(ARES_VERSION_STR));
1964 snprintf(buf, 20, "%d.%d", ev_version_major(), ev_version_minor());
1965 versions->Set(String::NewSymbol("ev"), String::New(buf));
1967 // Stupid code to slice out the version string.
1968 int c, l = strlen(OPENSSL_VERSION_TEXT);
1969 for (i = 0; i < l; i++) {
1970 c = OPENSSL_VERSION_TEXT[i];
1971 if ('0' <= c && c <= '9') {
1972 for (j = i + 1; j < l; j++) {
1973 c = OPENSSL_VERSION_TEXT[j];
1974 if (c == ' ') break;
1979 versions->Set(String::NewSymbol("openssl"),
1980 String::New(OPENSSL_VERSION_TEXT + i, j - i));
1986 process->Set(String::NewSymbol("platform"), String::New(PLATFORM));
1989 Local<Array> arguments = Array::New(argc - option_end_index + 1);
1990 arguments->Set(Integer::New(0), String::New(argv[0]));
1991 for (j = 1, i = option_end_index; i < argc; j++, i++) {
1992 Local<String> arg = String::New(argv[i]);
1993 arguments->Set(Integer::New(j), arg);
1996 process->Set(String::NewSymbol("ARGV"), arguments);
1997 process->Set(String::NewSymbol("argv"), arguments);
1999 // create process.env
2000 Local<ObjectTemplate> envTemplate = ObjectTemplate::New();
2001 envTemplate->SetNamedPropertyHandler(EnvGetter,
2007 Local<Object> env = envTemplate->NewInstance();
2008 process->Set(String::NewSymbol("env"), env);
2010 // create process.ENV
2011 // TODO: remove me at some point.
2012 Local<ObjectTemplate> ENVTemplate = ObjectTemplate::New();
2013 ENVTemplate->SetNamedPropertyHandler(EnvGetterWarn,
2019 Local<Object> ENV = ENVTemplate->NewInstance();
2020 process->Set(String::NewSymbol("ENV"), ENV);
2022 process->Set(String::NewSymbol("pid"), Integer::New(getpid()));
2026 process->Set(String::NewSymbol("_eval"), String::New(eval_string));
2029 size_t size = 2*PATH_MAX;
2030 char execPath[size];
2031 if (Platform::GetExecutablePath(execPath, &size) != 0) {
2032 // as a last ditch effort, fallback on argv[0] ?
2033 process->Set(String::NewSymbol("execPath"), String::New(argv[0]));
2035 process->Set(String::NewSymbol("execPath"), String::New(execPath, size));
2039 // define various internal methods
2040 NODE_SET_METHOD(process, "compile", Compile);
2041 NODE_SET_METHOD(process, "_needTickCallback", NeedTickCallback);
2042 NODE_SET_METHOD(process, "reallyExit", Exit);
2043 NODE_SET_METHOD(process, "chdir", Chdir);
2044 NODE_SET_METHOD(process, "cwd", Cwd);
2047 NODE_SET_METHOD(process, "getuid", GetUid);
2048 NODE_SET_METHOD(process, "setuid", SetUid);
2050 NODE_SET_METHOD(process, "setgid", SetGid);
2051 NODE_SET_METHOD(process, "getgid", GetGid);
2053 NODE_SET_METHOD(process, "umask", Umask);
2054 NODE_SET_METHOD(process, "dlopen", DLOpen);
2055 NODE_SET_METHOD(process, "_kill", Kill);
2058 NODE_SET_METHOD(process, "uptime", Uptime);
2059 NODE_SET_METHOD(process, "memoryUsage", MemoryUsage);
2061 NODE_SET_METHOD(process, "binding", Binding);
2063 // Assign the EventEmitter. It was created in main().
2064 process->Set(String::NewSymbol("EventEmitter"),
2065 EventEmitter::constructor_template->GetFunction());
2067 // Compile, execute the src/node.js file. (Which was included as static C
2068 // string in node_natives.h. 'natve_node' is the string containing that
2071 // The node.js file returns a function 'f'
2075 Local<Value> f_value = ExecuteString(MainSource(),
2076 IMMUTABLE_STRING("node.js"));
2077 if (try_catch.HasCaught()) {
2078 ReportException(try_catch, true);
2081 assert(f_value->IsFunction());
2082 Local<Function> f = Local<Function>::Cast(f_value);
2084 // Now we call 'f' with the 'process' variable that we've built up with
2085 // all our bindings. Inside node.js we'll take care of assigning things to
2088 // We start the process this way in order to be more modular. Developers
2089 // who do not like how 'src/node.js' setups the module system but do like
2090 // Node's I/O bindings may want to replace 'f' with their own function.
2092 // Add a reference to the global object
2093 Local<Object> global = v8::Context::GetCurrent()->Global();
2094 Local<Value> args[1] = { Local<Value>::New(process) };
2100 f->Call(global, 1, args);
2102 if (try_catch.HasCaught()) {
2103 ReportException(try_catch, true);
2108 static void PrintHelp();
2110 static void ParseDebugOpt(const char* arg) {
2113 use_debug_agent = true;
2114 if (!strcmp (arg, "--debug-brk")) {
2115 debug_wait_connect = true;
2117 } else if (!strcmp(arg, "--debug")) {
2119 } else if (strstr(arg, "--debug-brk=") == arg) {
2120 debug_wait_connect = true;
2121 p = 1 + strchr(arg, '=');
2122 debug_port = atoi(p);
2123 } else if (strstr(arg, "--debug=") == arg) {
2124 p = 1 + strchr(arg, '=');
2125 debug_port = atoi(p);
2127 if (p && debug_port > 1024 && debug_port < 65536)
2130 fprintf(stderr, "Bad debug option.\n");
2131 if (p) fprintf(stderr, "Debug port must be in range 1025 to 65535.\n");
2137 static void PrintHelp() {
2138 printf("Usage: node [options] script.js [arguments] \n"
2139 " node debug script.js [arguments] \n"
2142 " -v, --version print node's version\n"
2143 " --v8-options print v8 command line options\n"
2144 " --vars print various compiled-in variables\n"
2145 " --max-stack-size=val set max v8 stack size (bytes)\n"
2147 "Enviromental variables:\n"
2148 "NODE_PATH ':'-separated list of directories\n"
2149 " prefixed to the module search path,\n"
2151 "NODE_MODULE_CONTEXTS Set to 1 to load modules in their own\n"
2152 " global contexts.\n"
2153 "NODE_DISABLE_COLORS Set to 1 to disable colors in the REPL\n"
2155 "Documentation can be found at http://nodejs.org/\n");
2158 // Parse node command line arguments.
2159 static void ParseArgs(int *argc, char **argv) {
2162 // TODO use parse opts
2163 for (i = 1; i < *argc; i++) {
2164 const char *arg = argv[i];
2165 if (strstr(arg, "--debug") == arg) {
2167 argv[i] = const_cast<char*>("");
2168 } else if (strcmp(arg, "--version") == 0 || strcmp(arg, "-v") == 0) {
2169 printf("%s\n", NODE_VERSION);
2171 } else if (strcmp(arg, "--vars") == 0) {
2172 printf("NODE_PREFIX: %s\n", NODE_PREFIX);
2173 printf("NODE_CFLAGS: %s\n", NODE_CFLAGS);
2175 } else if (strstr(arg, "--max-stack-size=") == arg) {
2177 p = 1 + strchr(arg, '=');
2178 max_stack_size = atoi(p);
2179 argv[i] = const_cast<char*>("");
2180 } else if (strcmp(arg, "--help") == 0 || strcmp(arg, "-h") == 0) {
2183 } else if (strcmp(arg, "--eval") == 0 || strcmp(arg, "-e") == 0) {
2184 if (*argc <= i + 1) {
2185 fprintf(stderr, "Error: --eval requires an argument\n");
2188 argv[i] = const_cast<char*>("");
2189 eval_string = argv[++i];
2190 } else if (strcmp(arg, "--v8-options") == 0) {
2191 argv[i] = const_cast<char*>("--help");
2192 } else if (argv[i][0] != '-') {
2197 option_end_index = i;
2201 static void AtExit() {
2202 node::Stdio::Flush();
2203 node::Stdio::DisableRawMode(STDIN_FILENO);
2207 static void SignalExit(int signal) {
2208 Stdio::DisableRawMode(STDIN_FILENO);
2213 static void EnableDebug(bool wait_connect) {
2214 // Start the debug thread and it's associated TCP server on port 5858.
2215 bool r = Debug::EnableAgent("node " NODE_VERSION, debug_port);
2218 // Set up an empty handler so v8 will not continue until a debugger
2219 // attaches. This is the same behavior as Debug::EnableAgent(_,_,true)
2220 // except we don't break at the beginning of the script.
2221 // see Debugger::StartAgent in debug.cc of v8/src
2222 Debug::SetMessageHandler2(node::DebugBreakMessageHandler);
2225 // Crappy check that everything went well. FIXME
2228 // Print out some information.
2229 fprintf(stderr, "debugger listening on port %d\r\n", debug_port);
2233 static volatile bool hit_signal;
2236 static void EnableDebugSignalHandler(int signal) {
2237 // This is signal safe.
2239 v8::Debug::DebugBreak();
2243 static void DebugSignalCB(const Debug::EventDetails& details) {
2244 if (hit_signal && details.GetEvent() == v8::Break) {
2246 fprintf(stderr, "Hit SIGUSR1 - starting debugger agent.\n");
2254 static int RegisterSignalHandler(int signal, void (*handler)(int)) {
2255 struct sigaction sa;
2257 memset(&sa, 0, sizeof(sa));
2258 sa.sa_handler = handler;
2259 sigfillset(&sa.sa_mask);
2260 return sigaction(signal, &sa, NULL);
2265 int Start(int argc, char *argv[]) {
2266 // Hack aroung with the argv pointer. Used for process.title = "blah".
2267 argv = node::Platform::SetupArgs(argc, argv);
2269 // Parse a few arguments which are specific to Node.
2270 node::ParseArgs(&argc, argv);
2271 // Parse the rest of the args (up to the 'option_end_index' (where '--' was
2272 // in the command line))
2273 int v8argc = node::option_end_index;
2274 char **v8argv = argv;
2276 if (node::debug_wait_connect) {
2277 // v8argv is a copy of argv up to the script file argument +2 if --debug-brk
2278 // to expose the v8 debugger js object so that node.js can set
2279 // a breakpoint on the first line of the startup script
2281 v8argv = new char*[v8argc];
2282 memcpy(v8argv, argv, sizeof(argv) * node::option_end_index);
2283 v8argv[node::option_end_index] = const_cast<char*>("--expose_debug_as");
2284 v8argv[node::option_end_index + 1] = const_cast<char*>("v8debug");
2287 // For the normal stack which moves from high to low addresses when frames
2288 // are pushed, we can compute the limit as stack_size bytes below the
2289 // the address of a stack variable (e.g. &stack_var) as an approximation
2290 // of the start of the stack (we're assuming that we haven't pushed a lot
2292 if (node::max_stack_size != 0) {
2294 ResourceConstraints constraints;
2296 uint32_t *stack_limit = &stack_var - (node::max_stack_size / sizeof(uint32_t));
2297 constraints.set_stack_limit(stack_limit);
2298 SetResourceConstraints(&constraints); // Must be done before V8::Initialize
2300 V8::SetFlagsFromCommandLine(&v8argc, v8argv, false);
2304 RegisterSignalHandler(SIGPIPE, SIG_IGN);
2305 RegisterSignalHandler(SIGINT, SignalExit);
2306 RegisterSignalHandler(SIGTERM, SignalExit);
2310 // Initialize winsock and soem related caches
2312 #endif // __MINGW32__
2314 // Initialize the default ev loop.
2315 #if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
2316 ev_default_loop(EVBACKEND_KQUEUE);
2318 ev_default_loop(EVFLAG_AUTO);
2321 ev_prepare_init(&node::prepare_tick_watcher, node::PrepareTick);
2322 ev_prepare_start(EV_DEFAULT_UC_ &node::prepare_tick_watcher);
2323 ev_unref(EV_DEFAULT_UC);
2325 ev_check_init(&node::check_tick_watcher, node::CheckTick);
2326 ev_check_start(EV_DEFAULT_UC_ &node::check_tick_watcher);
2327 ev_unref(EV_DEFAULT_UC);
2329 ev_idle_init(&node::tick_spinner, node::Spin);
2331 ev_check_init(&node::gc_check, node::Check);
2332 ev_check_start(EV_DEFAULT_UC_ &node::gc_check);
2333 ev_unref(EV_DEFAULT_UC);
2335 ev_idle_init(&node::gc_idle, node::Idle);
2336 ev_timer_init(&node::gc_timer, node::CheckStatus, 5., 5.);
2339 // Setup the EIO thread pool
2340 { // It requires 3, yes 3, watchers.
2341 ev_idle_init(&node::eio_poller, node::DoPoll);
2343 ev_async_init(&node::eio_want_poll_notifier, node::WantPollNotifier);
2344 ev_async_start(EV_DEFAULT_UC_ &node::eio_want_poll_notifier);
2345 ev_unref(EV_DEFAULT_UC);
2347 ev_async_init(&node::eio_done_poll_notifier, node::DonePollNotifier);
2348 ev_async_start(EV_DEFAULT_UC_ &node::eio_done_poll_notifier);
2349 ev_unref(EV_DEFAULT_UC);
2351 eio_init(node::EIOWantPoll, node::EIODonePoll);
2352 // Don't handle more than 10 reqs on each eio_poll(). This is to avoid
2353 // race conditions. See test/simple/test-eio-race.js
2354 eio_set_max_poll_reqs(10);
2358 HandleScope handle_scope;
2360 V8::SetFatalErrorHandler(node::OnFatalError);
2363 // Initialize the async watcher for receiving messages from the debug
2364 // thread and marshal it into the main thread. DebugMessageCallback()
2365 // is called from the main thread to execute a random bit of javascript
2366 // - which will give V8 control so it can handle whatever new message
2367 // had been received on the debug thread.
2368 ev_async_init(&node::debug_watcher, node::DebugMessageCallback);
2369 ev_set_priority(&node::debug_watcher, EV_MAXPRI);
2370 // Set the callback DebugMessageDispatch which is called from the debug
2372 Debug::SetDebugMessageDispatchHandler(node::DebugMessageDispatch);
2373 // Start the async watcher.
2374 ev_async_start(EV_DEFAULT_UC_ &node::debug_watcher);
2375 // unref it so that we exit the event loop despite it being active.
2376 ev_unref(EV_DEFAULT_UC);
2379 // If the --debug flag was specified then initialize the debug thread.
2380 if (node::use_debug_agent) {
2381 EnableDebug(debug_wait_connect);
2384 RegisterSignalHandler(SIGUSR1, EnableDebugSignalHandler);
2385 Debug::SetDebugEventListener2(DebugSignalCB);
2389 // Create the one and only Context.
2390 Persistent<v8::Context> context = v8::Context::New();
2391 v8::Context::Scope context_scope(context);
2393 atexit(node::AtExit);
2395 // Create all the objects, load modules, do everything.
2396 // so your next reading stop should be node::Load()!
2397 node::Load(argc, argv);
2399 // TODO Probably don't need to start this each time.
2400 // Avoids failing on test/simple/test-eio-race3.js though
2401 ev_idle_start(EV_DEFAULT_UC_ &eio_poller);
2403 // All our arguments are loaded. We've evaluated all of the scripts. We
2404 // might even have created TCP servers. Now we enter the main eventloop. If
2405 // there are no watchers on the loop (except for the ones that were
2406 // ev_unref'd) then this function exits. As long as there are active
2407 // watchers, it blocks.
2408 ev_loop(EV_DEFAULT_UC_ 0);
2411 // process.emit('exit')
2412 Local<Value> emit_v = process->Get(String::New("emit"));
2413 assert(emit_v->IsFunction());
2414 Local<Function> emit = Local<Function>::Cast(emit_v);
2415 Local<Value> args[] = { String::New("exit") };
2417 emit->Call(process, 1, args);
2418 if (try_catch.HasCaught()) {
2419 FatalException(try_catch);