blob: ab755d743bc336072b85b35509dc6d11043d3742 [file] [log] [blame]
Ryan Dahl55048cd2011-03-10 08:54:521// Copyright Joyent, Inc. and other Node contributors.
2//
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:
10//
11// The above copyright notice and this permission notice shall be included
12// in all copies or substantial portions of the Software.
13//
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.
Bert Beldere0f47be2011-01-17 23:22:3621
Ryand6c9d312009-09-11 14:02:2922#include <node.h>
Ryan63a9cd32009-04-15 08:08:2823
Ryan Dahlefca3342011-05-13 02:16:4024#include <uv.h>
25
Bert Beldere0f47be2011-01-17 23:22:3626#include <v8-debug.h>
Ryan Dahlb3ddb892011-10-26 18:31:1227#ifdef HAVE_DTRACE
28# include <node_dtrace.h>
29#endif
Ryan Dahl4635ed72010-03-11 20:40:1930
Bert Beldere0f47be2011-01-17 23:22:3631#include <locale.h>
Bert Belder9cec08e2011-05-23 23:42:2232#include <signal.h>
Ryan19478ed2009-03-03 00:56:1533#include <stdio.h>
Peter Bright13d6a1f2011-08-06 04:23:2534#if defined(_MSC_VER)
35#define snprintf _snprintf
36#endif
Ryan34a6f102009-05-28 12:47:1637#include <stdlib.h>
Ryan Dahlc90e44e2010-05-10 23:38:4738#include <string.h>
Peter Bright13d6a1f2011-08-06 04:23:2539#if !defined(_MSC_VER)
40#include <strings.h>
41#else
42#define strcasecmp _stricmp
43#endif
Ryan82d986d2009-09-02 18:18:5044#include <limits.h> /* PATH_MAX */
Ryan19478ed2009-03-03 00:56:1545#include <assert.h>
Peter Bright13d6a1f2011-08-06 04:23:2546#if !defined(_MSC_VER)
47#include <unistd.h> /* setuid, getuid */
48#else
49#include <direct.h>
Peter Bright13d6a1f2011-08-06 04:23:2550#include <process.h>
51#define getpid _getpid
Peter Brightb9d77772011-08-11 01:45:5652#include <io.h>
53#define umask _umask
54typedef int mode_t;
Peter Bright13d6a1f2011-08-06 04:23:2555#endif
Michael Carter8ea6adc2009-09-01 09:39:3056#include <errno.h>
Michael Cartera3860762010-02-08 06:13:1057#include <sys/types.h>
Ryane02b71e2009-03-03 23:31:3758
Bert Beldere0f47be2011-01-17 23:22:3659#ifdef __POSIX__
Bert Beldera177d602010-11-25 00:02:5560# include <pwd.h> /* getpwnam() */
61# include <grp.h> /* getgrnam() */
62#endif
63
Ryan Dahl630bb7a2009-12-13 07:42:4564#include <node_buffer.h>
Igor Zinkovskyf35a3962011-10-28 22:34:2465#ifdef __POSIX__
66# include <node_io_watcher.h>
67#endif
Ryan Dahla5df0f62009-10-27 10:46:5868#include <node_file.h>
Ryan Dahl42ee1692010-01-24 19:21:4569#include <node_http_parser.h>
Bert Belder406f44a2011-06-08 02:41:2870#ifdef __POSIX__
71# include <node_signal_watcher.h>
72# include <node_stat_watcher.h>
73#endif
Ryan Dahla5df0f62009-10-27 10:46:5874#include <node_constants.h>
Ryan Dahlc4636a52010-10-12 18:49:4175#include <node_javascript.h>
Ryan Dahl0ae02c92009-10-09 15:47:0476#include <node_version.h>
Tom Hughes74954ce2011-03-08 06:00:5177#include <node_string.h>
Peter Bright13d6a1f2011-08-06 04:23:2578#if HAVE_OPENSSL
Bert Beldere0f47be2011-01-17 23:22:3679# include <node_crypto.h>
Rhys Jonesfb3a9cd2010-04-02 23:11:5380#endif
Herbert Vojcikc2a06722010-04-17 15:18:1581#include <node_script.h>
Ben Noordhuis7cab4d62011-07-26 21:20:2982#include <v8_typed_array.h>
Ryan6dd850a2009-09-08 12:59:4383
Ryan19478ed2009-03-03 00:56:1584using namespace v8;
Ryan19478ed2009-03-03 00:56:1585
Rasmus Andersson50443f02010-10-11 15:19:1186# ifdef __APPLE__
87# include <crt_externs.h>
88# define environ (*_NSGetEnviron())
Peter Bright13d6a1f2011-08-06 04:23:2589# elif !defined(_MSC_VER)
Ryan3e4fc9f2009-09-10 14:48:3890extern char **environ;
Rasmus Andersson50443f02010-10-11 15:19:1191# endif
Ryan3e4fc9f2009-09-10 14:48:3892
Ryand6c9d312009-09-11 14:02:2993namespace node {
94
Ben Noordhuis809fdf22011-12-09 20:49:1095
Ben Noordhuis74a82152012-02-03 15:32:0096static Persistent<Object> process;
97
98static Persistent<String> errno_symbol;
99static Persistent<String> syscall_symbol;
100static Persistent<String> errpath_symbol;
101static Persistent<String> code_symbol;
102
103static Persistent<String> rss_symbol;
104static Persistent<String> heap_total_symbol;
105static Persistent<String> heap_used_symbol;
106
107static Persistent<String> listeners_symbol;
108static Persistent<String> uncaught_exception_symbol;
109static Persistent<String> emit_symbol;
110
111
112static bool print_eval = false;
113static char *eval_string = NULL;
114static int option_end_index = 0;
115static bool use_debug_agent = false;
116static bool debug_wait_connect = false;
117static int debug_port=5858;
118static int max_stack_size = 0;
119
120static uv_check_t check_tick_watcher;
121static uv_prepare_t prepare_tick_watcher;
122static uv_idle_t tick_spinner;
123static bool need_tick_cb;
124static Persistent<String> tick_callback_sym;
125
126
127#ifdef OPENSSL_NPN_NEGOTIATED
128static bool use_npn = true;
129#else
130static bool use_npn = false;
131#endif
132
133#ifdef SSL_CTRL_SET_TLSEXT_SERVERNAME_CB
134static bool use_sni = true;
135#else
136static bool use_sni = false;
137#endif
138
139#ifdef __POSIX__
140// Buffer for getpwnam_r(), getgrpam_r() and other misc callers; keep this
141// scoped at file-level rather than method-level to avoid excess stack usage.
142static char getbuf[PATH_MAX + 1];
143#endif
144
145// We need to notify V8 when we're idle so that it can run the garbage
146// collector. The interface to this is V8::IdleNotification(). It returns
147// true if the heap hasn't be fully compacted, and needs to be run again.
148// Returning false means that it doesn't have anymore work to do.
149//
150// A rather convoluted algorithm has been devised to determine when Node is
151// idle. You'll have to figure it out for yourself.
152static uv_check_t gc_check;
153static uv_idle_t gc_idle;
154static uv_timer_t gc_timer;
155bool need_gc;
156
157// process-relative uptime base, initialized at start-up
158static double prog_start_time;
159
160#define FAST_TICK 700.
161#define GC_WAIT_TIME 5000.
162#define RPM_SAMPLES 100
163#define TICK_TIME(n) tick_times[(tick_time_head - (n)) % RPM_SAMPLES]
164static int64_t tick_times[RPM_SAMPLES];
165static int tick_time_head;
Ben Noordhuis2df81c52011-12-09 17:49:17166
Ryan Dahlf657d582011-06-22 12:06:26167static void CheckStatus(uv_timer_t* watcher, int status);
Ben Noordhuis809fdf22011-12-09 20:49:10168
Ryan Dahl3ac6dee2010-05-08 02:05:59169static void StartGCTimer () {
Ryan Dahl7a5977b2011-06-07 16:37:27170 if (!uv_is_active((uv_handle_t*) &gc_timer)) {
Ryan Dahl7547c7d2011-12-07 01:00:33171 uv_timer_start(&gc_timer, node::CheckStatus, 5000, 5000);
Ryan Dahlac3bc2e2010-04-15 08:29:39172 }
173}
174
Ryan Dahl3ac6dee2010-05-08 02:05:59175static void StopGCTimer () {
Ryan Dahl7a5977b2011-06-07 16:37:27176 if (uv_is_active((uv_handle_t*) &gc_timer)) {
Bert Belder9cec08e2011-05-23 23:42:22177 uv_timer_stop(&gc_timer);
Ryan Dahlac3bc2e2010-04-15 08:29:39178 }
179}
Ryan Dahldaacb812010-02-21 02:23:21180
Ryan Dahlf657d582011-06-22 12:06:26181static void Idle(uv_idle_t* watcher, int status) {
Ryan Dahl7a5977b2011-06-07 16:37:27182 assert((uv_idle_t*) watcher == &gc_idle);
Ryan Dahl801fb8a2010-04-05 20:51:32183
Ryan Dahl801fb8a2010-04-05 20:51:32184 if (V8::IdleNotification()) {
Ryan Dahl7a5977b2011-06-07 16:37:27185 uv_idle_stop(&gc_idle);
Ryan Dahl3ac6dee2010-05-08 02:05:59186 StopGCTimer();
Ryan Dahl801fb8a2010-04-05 20:51:32187 }
Ryan Dahl801fb8a2010-04-05 20:51:32188}
189
190
Ryan Dahl3ac6dee2010-05-08 02:05:59191// Called directly after every call to select() (or epoll, or whatever)
Ryan Dahlf657d582011-06-22 12:06:26192static void Check(uv_check_t* watcher, int status) {
193 assert(watcher == &gc_check);
Ryan Dahl801fb8a2010-04-05 20:51:32194
Ben Noordhuis74a82152012-02-03 15:32:00195 tick_times[tick_time_head] = uv_now(uv_default_loop());
Ryan Dahl3ac6dee2010-05-08 02:05:59196 tick_time_head = (tick_time_head + 1) % RPM_SAMPLES;
Ryan Dahl801fb8a2010-04-05 20:51:32197
Ryan Dahl3ac6dee2010-05-08 02:05:59198 StartGCTimer();
Ryan Dahl801fb8a2010-04-05 20:51:32199
Ryan Dahl3ac6dee2010-05-08 02:05:59200 for (int i = 0; i < (int)(GC_WAIT_TIME/FAST_TICK); i++) {
201 double d = TICK_TIME(i+1) - TICK_TIME(i+2);
202 //printf("d = %f\n", d);
203 // If in the last 5 ticks the difference between
204 // ticks was less than 0.7 seconds, then continue.
205 if (d < FAST_TICK) {
206 //printf("---\n");
207 return;
208 }
Ryan Dahl801fb8a2010-04-05 20:51:32209 }
Ryan Dahl3ac6dee2010-05-08 02:05:59210
211 // Otherwise start the gc!
212
213 //fprintf(stderr, "start idle 2\n");
Ryan Dahl7547c7d2011-12-07 01:00:33214 uv_idle_start(&gc_idle, node::Idle);
Ryan Dahldaacb812010-02-21 02:23:21215}
216
Ryan Dahlf80cc692010-01-06 09:17:58217
Ryan Dahl17f3ffa2010-09-09 17:30:37218static void Tick(void) {
Ryan Dahl4e7e2f82010-04-13 22:39:15219 // Avoid entering a V8 scope.
220 if (!need_tick_cb) return;
221
222 need_tick_cb = false;
Ryan Dahl7a5977b2011-06-07 16:37:27223 if (uv_is_active((uv_handle_t*) &tick_spinner)) {
Ryan Dahl207901e2011-05-23 22:38:54224 uv_idle_stop(&tick_spinner);
Ben Noordhuis74a82152012-02-03 15:32:00225 uv_unref(uv_default_loop());
Ryan Dahl207901e2011-05-23 22:38:54226 }
Ryan Dahl4e7e2f82010-04-13 22:39:15227
228 HandleScope scope;
229
230 if (tick_callback_sym.IsEmpty()) {
231 // Lazily set the symbol
232 tick_callback_sym =
233 Persistent<String>::New(String::NewSymbol("_tickCallback"));
234 }
235
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);
239
240 TryCatch try_catch;
241
242 cb->Call(process, 0, NULL);
243
244 if (try_catch.HasCaught()) {
245 FatalException(try_catch);
246 }
247}
248
249
Ryan Dahlf657d582011-06-22 12:06:26250static void Spin(uv_idle_t* handle, int status) {
Bert Belder09ac99f2011-06-08 01:46:29251 assert((uv_idle_t*) handle == &tick_spinner);
252 assert(status == 0);
253 Tick();
254}
255
256
257static Handle<Value> NeedTickCallback(const Arguments& args) {
258 HandleScope scope;
259 need_tick_cb = true;
260 // TODO: this tick_spinner shouldn't be necessary. An ev_prepare should be
261 // sufficent, the problem is only in the case of the very last "tick" -
262 // there is nothing left to do in the event loop and libev will exit. The
263 // ev_prepare callback isn't called before exiting. Thus we start this
264 // tick_spinner to keep the event loop alive long enough to handle it.
265 if (!uv_is_active((uv_handle_t*) &tick_spinner)) {
266 uv_idle_start(&tick_spinner, Spin);
Ben Noordhuis74a82152012-02-03 15:32:00267 uv_ref(uv_default_loop());
Bert Belder09ac99f2011-06-08 01:46:29268 }
269 return Undefined();
270}
271
272
Ryan Dahlf657d582011-06-22 12:06:26273static void PrepareTick(uv_prepare_t* handle, int status) {
274 assert(handle == &prepare_tick_watcher);
Ryan Dahla46c63b2011-05-13 14:06:20275 assert(status == 0);
Ryan Dahl17f3ffa2010-09-09 17:30:37276 Tick();
277}
278
279
Ryan Dahlf657d582011-06-22 12:06:26280static void CheckTick(uv_check_t* handle, int status) {
281 assert(handle == &check_tick_watcher);
Ryan Dahl91bd1442011-05-13 14:09:28282 assert(status == 0);
Ryan Dahl17f3ffa2010-09-09 17:30:37283 Tick();
284}
285
Ryan Dahlc9e27b12010-04-23 00:53:45286static inline const char *errno_string(int errorno) {
287#define ERRNO_CASE(e) case e: return #e;
288 switch (errorno) {
289
290#ifdef EACCES
291 ERRNO_CASE(EACCES);
292#endif
293
294#ifdef EADDRINUSE
295 ERRNO_CASE(EADDRINUSE);
296#endif
297
298#ifdef EADDRNOTAVAIL
299 ERRNO_CASE(EADDRNOTAVAIL);
300#endif
301
302#ifdef EAFNOSUPPORT
303 ERRNO_CASE(EAFNOSUPPORT);
304#endif
305
306#ifdef EAGAIN
307 ERRNO_CASE(EAGAIN);
Ryan Dahl9b2aac62010-04-28 19:58:00308#endif
309
310#ifdef EWOULDBLOCK
311# if EAGAIN != EWOULDBLOCK
Ryan Dahlc9e27b12010-04-23 00:53:45312 ERRNO_CASE(EWOULDBLOCK);
313# endif
314#endif
315
316#ifdef EALREADY
317 ERRNO_CASE(EALREADY);
318#endif
319
320#ifdef EBADF
321 ERRNO_CASE(EBADF);
322#endif
323
324#ifdef EBADMSG
325 ERRNO_CASE(EBADMSG);
326#endif
327
328#ifdef EBUSY
329 ERRNO_CASE(EBUSY);
330#endif
331
332#ifdef ECANCELED
333 ERRNO_CASE(ECANCELED);
334#endif
335
336#ifdef ECHILD
337 ERRNO_CASE(ECHILD);
338#endif
339
340#ifdef ECONNABORTED
341 ERRNO_CASE(ECONNABORTED);
342#endif
343
344#ifdef ECONNREFUSED
345 ERRNO_CASE(ECONNREFUSED);
346#endif
347
348#ifdef ECONNRESET
349 ERRNO_CASE(ECONNRESET);
350#endif
351
352#ifdef EDEADLK
353 ERRNO_CASE(EDEADLK);
354#endif
355
356#ifdef EDESTADDRREQ
357 ERRNO_CASE(EDESTADDRREQ);
358#endif
359
360#ifdef EDOM
361 ERRNO_CASE(EDOM);
362#endif
363
364#ifdef EDQUOT
365 ERRNO_CASE(EDQUOT);
366#endif
367
368#ifdef EEXIST
369 ERRNO_CASE(EEXIST);
370#endif
371
372#ifdef EFAULT
373 ERRNO_CASE(EFAULT);
374#endif
375
376#ifdef EFBIG
377 ERRNO_CASE(EFBIG);
378#endif
379
380#ifdef EHOSTUNREACH
381 ERRNO_CASE(EHOSTUNREACH);
382#endif
383
384#ifdef EIDRM
385 ERRNO_CASE(EIDRM);
386#endif
387
388#ifdef EILSEQ
389 ERRNO_CASE(EILSEQ);
390#endif
391
392#ifdef EINPROGRESS
393 ERRNO_CASE(EINPROGRESS);
394#endif
395
396#ifdef EINTR
397 ERRNO_CASE(EINTR);
398#endif
399
400#ifdef EINVAL
401 ERRNO_CASE(EINVAL);
402#endif
403
404#ifdef EIO
405 ERRNO_CASE(EIO);
406#endif
407
408#ifdef EISCONN
409 ERRNO_CASE(EISCONN);
410#endif
411
412#ifdef EISDIR
413 ERRNO_CASE(EISDIR);
414#endif
415
416#ifdef ELOOP
417 ERRNO_CASE(ELOOP);
418#endif
419
420#ifdef EMFILE
421 ERRNO_CASE(EMFILE);
422#endif
423
424#ifdef EMLINK
425 ERRNO_CASE(EMLINK);
426#endif
427
428#ifdef EMSGSIZE
429 ERRNO_CASE(EMSGSIZE);
430#endif
431
432#ifdef EMULTIHOP
433 ERRNO_CASE(EMULTIHOP);
434#endif
435
436#ifdef ENAMETOOLONG
437 ERRNO_CASE(ENAMETOOLONG);
438#endif
439
440#ifdef ENETDOWN
441 ERRNO_CASE(ENETDOWN);
442#endif
443
444#ifdef ENETRESET
445 ERRNO_CASE(ENETRESET);
446#endif
447
448#ifdef ENETUNREACH
449 ERRNO_CASE(ENETUNREACH);
450#endif
451
452#ifdef ENFILE
453 ERRNO_CASE(ENFILE);
454#endif
455
456#ifdef ENOBUFS
457 ERRNO_CASE(ENOBUFS);
458#endif
459
460#ifdef ENODATA
461 ERRNO_CASE(ENODATA);
462#endif
463
464#ifdef ENODEV
465 ERRNO_CASE(ENODEV);
466#endif
467
468#ifdef ENOENT
469 ERRNO_CASE(ENOENT);
470#endif
471
472#ifdef ENOEXEC
473 ERRNO_CASE(ENOEXEC);
474#endif
475
Ryan Dahlc9e27b12010-04-23 00:53:45476#ifdef ENOLINK
477 ERRNO_CASE(ENOLINK);
478#endif
479
Ryan Dahl3bb21b52010-04-28 22:07:15480#ifdef ENOLCK
481# if ENOLINK != ENOLCK
482 ERRNO_CASE(ENOLCK);
483# endif
484#endif
485
Ryan Dahlc9e27b12010-04-23 00:53:45486#ifdef ENOMEM
487 ERRNO_CASE(ENOMEM);
488#endif
489
490#ifdef ENOMSG
491 ERRNO_CASE(ENOMSG);
492#endif
493
494#ifdef ENOPROTOOPT
495 ERRNO_CASE(ENOPROTOOPT);
496#endif
497
498#ifdef ENOSPC
499 ERRNO_CASE(ENOSPC);
500#endif
501
502#ifdef ENOSR
503 ERRNO_CASE(ENOSR);
504#endif
505
506#ifdef ENOSTR
507 ERRNO_CASE(ENOSTR);
508#endif
509
510#ifdef ENOSYS
511 ERRNO_CASE(ENOSYS);
512#endif
513
514#ifdef ENOTCONN
515 ERRNO_CASE(ENOTCONN);
516#endif
517
518#ifdef ENOTDIR
519 ERRNO_CASE(ENOTDIR);
520#endif
521
522#ifdef ENOTEMPTY
523 ERRNO_CASE(ENOTEMPTY);
524#endif
525
526#ifdef ENOTSOCK
527 ERRNO_CASE(ENOTSOCK);
528#endif
529
530#ifdef ENOTSUP
531 ERRNO_CASE(ENOTSUP);
532#else
533# ifdef EOPNOTSUPP
534 ERRNO_CASE(EOPNOTSUPP);
535# endif
536#endif
537
538#ifdef ENOTTY
539 ERRNO_CASE(ENOTTY);
540#endif
541
542#ifdef ENXIO
543 ERRNO_CASE(ENXIO);
544#endif
545
546
547#ifdef EOVERFLOW
548 ERRNO_CASE(EOVERFLOW);
549#endif
550
551#ifdef EPERM
552 ERRNO_CASE(EPERM);
553#endif
554
555#ifdef EPIPE
556 ERRNO_CASE(EPIPE);
557#endif
558
559#ifdef EPROTO
560 ERRNO_CASE(EPROTO);
561#endif
562
563#ifdef EPROTONOSUPPORT
564 ERRNO_CASE(EPROTONOSUPPORT);
565#endif
566
567#ifdef EPROTOTYPE
568 ERRNO_CASE(EPROTOTYPE);
569#endif
570
571#ifdef ERANGE
572 ERRNO_CASE(ERANGE);
573#endif
574
575#ifdef EROFS
576 ERRNO_CASE(EROFS);
577#endif
578
579#ifdef ESPIPE
580 ERRNO_CASE(ESPIPE);
581#endif
582
583#ifdef ESRCH
584 ERRNO_CASE(ESRCH);
585#endif
586
587#ifdef ESTALE
588 ERRNO_CASE(ESTALE);
589#endif
590
591#ifdef ETIME
592 ERRNO_CASE(ETIME);
593#endif
594
595#ifdef ETIMEDOUT
596 ERRNO_CASE(ETIMEDOUT);
597#endif
598
599#ifdef ETXTBSY
600 ERRNO_CASE(ETXTBSY);
601#endif
602
603#ifdef EXDEV
604 ERRNO_CASE(EXDEV);
605#endif
606
607 default: return "";
608 }
609}
610
Felix Geisendörferf8a3cf92010-04-28 13:04:08611const char *signo_string(int signo) {
612#define SIGNO_CASE(e) case e: return #e;
613 switch (signo) {
614
615#ifdef SIGHUP
616 SIGNO_CASE(SIGHUP);
617#endif
618
619#ifdef SIGINT
620 SIGNO_CASE(SIGINT);
621#endif
622
623#ifdef SIGQUIT
624 SIGNO_CASE(SIGQUIT);
625#endif
626
627#ifdef SIGILL
628 SIGNO_CASE(SIGILL);
629#endif
630
631#ifdef SIGTRAP
632 SIGNO_CASE(SIGTRAP);
633#endif
634
635#ifdef SIGABRT
636 SIGNO_CASE(SIGABRT);
637#endif
638
639#ifdef SIGIOT
640# if SIGABRT != SIGIOT
641 SIGNO_CASE(SIGIOT);
642# endif
643#endif
644
645#ifdef SIGBUS
646 SIGNO_CASE(SIGBUS);
647#endif
648
649#ifdef SIGFPE
650 SIGNO_CASE(SIGFPE);
651#endif
652
653#ifdef SIGKILL
654 SIGNO_CASE(SIGKILL);
655#endif
656
657#ifdef SIGUSR1
658 SIGNO_CASE(SIGUSR1);
659#endif
660
661#ifdef SIGSEGV
662 SIGNO_CASE(SIGSEGV);
663#endif
664
665#ifdef SIGUSR2
666 SIGNO_CASE(SIGUSR2);
667#endif
668
669#ifdef SIGPIPE
670 SIGNO_CASE(SIGPIPE);
671#endif
672
673#ifdef SIGALRM
674 SIGNO_CASE(SIGALRM);
675#endif
676
677 SIGNO_CASE(SIGTERM);
Bert Belderdcc35082010-11-25 00:04:31678
679#ifdef SIGCHLD
Felix Geisendörferf8a3cf92010-04-28 13:04:08680 SIGNO_CASE(SIGCHLD);
Bert Belderdcc35082010-11-25 00:04:31681#endif
Felix Geisendörferf8a3cf92010-04-28 13:04:08682
683#ifdef SIGSTKFLT
684 SIGNO_CASE(SIGSTKFLT);
685#endif
686
687
688#ifdef SIGCONT
689 SIGNO_CASE(SIGCONT);
690#endif
691
692#ifdef SIGSTOP
693 SIGNO_CASE(SIGSTOP);
694#endif
695
696#ifdef SIGTSTP
697 SIGNO_CASE(SIGTSTP);
698#endif
699
700#ifdef SIGTTIN
701 SIGNO_CASE(SIGTTIN);
702#endif
703
704#ifdef SIGTTOU
705 SIGNO_CASE(SIGTTOU);
706#endif
707
708#ifdef SIGURG
709 SIGNO_CASE(SIGURG);
710#endif
711
712#ifdef SIGXCPU
713 SIGNO_CASE(SIGXCPU);
714#endif
715
716#ifdef SIGXFSZ
717 SIGNO_CASE(SIGXFSZ);
718#endif
719
720#ifdef SIGVTALRM
721 SIGNO_CASE(SIGVTALRM);
722#endif
723
724#ifdef SIGPROF
725 SIGNO_CASE(SIGPROF);
726#endif
727
728#ifdef SIGWINCH
729 SIGNO_CASE(SIGWINCH);
730#endif
731
732#ifdef SIGIO
733 SIGNO_CASE(SIGIO);
734#endif
735
736#ifdef SIGPOLL
Ryan Dahl3bb21b52010-04-28 22:07:15737# if SIGPOLL != SIGIO
Felix Geisendörferf8a3cf92010-04-28 13:04:08738 SIGNO_CASE(SIGPOLL);
Ryan Dahl3bb21b52010-04-28 22:07:15739# endif
Felix Geisendörferf8a3cf92010-04-28 13:04:08740#endif
741
742#ifdef SIGLOST
743 SIGNO_CASE(SIGLOST);
744#endif
745
746#ifdef SIGPWR
Raffaele Senab3b81d62010-06-09 04:08:05747# if SIGPWR != SIGLOST
Felix Geisendörferf8a3cf92010-04-28 13:04:08748 SIGNO_CASE(SIGPWR);
Raffaele Senab3b81d62010-06-09 04:08:05749# endif
Felix Geisendörferf8a3cf92010-04-28 13:04:08750#endif
751
752#ifdef SIGSYS
753 SIGNO_CASE(SIGSYS);
754#endif
755
Felix Geisendörferf8a3cf92010-04-28 13:04:08756 default: return "";
757 }
758}
759
Ryan Dahlc9e27b12010-04-23 00:53:45760
761Local<Value> ErrnoException(int errorno,
762 const char *syscall,
visionmedia45948e02010-05-14 14:52:49763 const char *msg,
764 const char *path) {
765 Local<Value> e;
Ryan Dahlc9e27b12010-04-23 00:53:45766 Local<String> estring = String::NewSymbol(errno_string(errorno));
Bert Belder2ce09612011-01-17 21:47:59767 if (!msg[0]) {
Bert Belder2ce09612011-01-17 21:47:59768 msg = strerror(errorno);
Bert Belder2ce09612011-01-17 21:47:59769 }
Ryan Dahlc9e27b12010-04-23 00:53:45770 Local<String> message = String::NewSymbol(msg);
771
772 Local<String> cons1 = String::Concat(estring, String::NewSymbol(", "));
773 Local<String> cons2 = String::Concat(cons1, message);
774
Ryan Dahl6cc42922011-10-19 23:53:07775 if (syscall_symbol.IsEmpty()) {
Ryan Dahlc9e27b12010-04-23 00:53:45776 syscall_symbol = NODE_PSYMBOL("syscall");
777 errno_symbol = NODE_PSYMBOL("errno");
visionmedia45948e02010-05-14 14:52:49778 errpath_symbol = NODE_PSYMBOL("path");
Ryan Dahlaa95e572011-02-04 22:35:14779 code_symbol = NODE_PSYMBOL("code");
Ryan Dahlc9e27b12010-04-23 00:53:45780 }
781
visionmedia45948e02010-05-14 14:52:49782 if (path) {
783 Local<String> cons3 = String::Concat(cons2, String::NewSymbol(" '"));
784 Local<String> cons4 = String::Concat(cons3, String::New(path));
785 Local<String> cons5 = String::Concat(cons4, String::NewSymbol("'"));
786 e = Exception::Error(cons5);
787 } else {
788 e = Exception::Error(cons2);
789 }
790
791 Local<Object> obj = e->ToObject();
792
Ryan Dahlc9e27b12010-04-23 00:53:45793 obj->Set(errno_symbol, Integer::New(errorno));
Ryan Dahlaa95e572011-02-04 22:35:14794 obj->Set(code_symbol, estring);
visionmedia45948e02010-05-14 14:52:49795 if (path) obj->Set(errpath_symbol, String::New(path));
Ryan Dahlc9e27b12010-04-23 00:53:45796 if (syscall) obj->Set(syscall_symbol, String::NewSymbol(syscall));
797 return e;
798}
799
800
Bert Belder823a4432011-12-01 23:02:51801static const char* get_uv_errno_string(int errorno) {
802 uv_err_t err;
803 memset(&err, 0, sizeof err);
804 err.code = (uv_err_code)errorno;
805 return uv_err_name(err);
806}
807
808
809static const char* get_uv_errno_message(int errorno) {
810 uv_err_t err;
811 memset(&err, 0, sizeof err);
812 err.code = (uv_err_code)errorno;
813 return uv_strerror(err);
814}
815
816
817// hack alert! copy of ErrnoException, tuned for uv errors
818Local<Value> UVException(int errorno,
819 const char *syscall,
820 const char *msg,
821 const char *path) {
Bert Belder823a4432011-12-01 23:02:51822 if (syscall_symbol.IsEmpty()) {
823 syscall_symbol = NODE_PSYMBOL("syscall");
824 errno_symbol = NODE_PSYMBOL("errno");
825 errpath_symbol = NODE_PSYMBOL("path");
826 code_symbol = NODE_PSYMBOL("code");
827 }
828
829 if (!msg || !msg[0])
830 msg = get_uv_errno_message(errorno);
831
Bert Belder641f2be2011-12-02 01:14:04832 Local<String> estring = String::NewSymbol(get_uv_errno_string(errorno));
Bert Belder823a4432011-12-01 23:02:51833 Local<String> message = String::NewSymbol(msg);
834 Local<String> cons1 = String::Concat(estring, String::NewSymbol(", "));
835 Local<String> cons2 = String::Concat(cons1, message);
836
837 Local<Value> e;
838
839 Local<String> path_str;
840
841 if (path) {
842#ifdef _WIN32
843 if (strncmp(path, "\\\\?\\UNC\\", 8) == 0) {
844 path_str = String::Concat(String::New("\\\\"), String::New(path + 8));
845 } else if (strncmp(path, "\\\\?\\", 4) == 0) {
846 path_str = String::New(path + 4);
847 } else {
848 path_str = String::New(path);
849 }
850#else
851 path_str = String::New(path);
852#endif
853
854 Local<String> cons3 = String::Concat(cons2, String::NewSymbol(" '"));
855 Local<String> cons4 = String::Concat(cons3, path_str);
856 Local<String> cons5 = String::Concat(cons4, String::NewSymbol("'"));
857 e = Exception::Error(cons5);
858 } else {
859 e = Exception::Error(cons2);
860 }
861
862 Local<Object> obj = e->ToObject();
863
864 // TODO errno should probably go
865 obj->Set(errno_symbol, Integer::New(errorno));
866 obj->Set(code_symbol, estring);
867 if (path) obj->Set(errpath_symbol, path_str);
868 if (syscall) obj->Set(syscall_symbol, String::NewSymbol(syscall));
869 return e;
870}
871
872
Bert Belder6ee73a22011-11-04 15:10:48873#ifdef _WIN32
Igor Zinkovsky500c8f42011-12-15 20:36:05874// Does about the same as strerror(),
875// but supports all windows error messages
876static const char *winapi_strerror(const int errorno) {
877 char *errmsg = NULL;
878
879 FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
880 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, errorno,
881 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&errmsg, 0, NULL);
882
883 if (errmsg) {
884 // Remove trailing newlines
885 for (int i = strlen(errmsg) - 1;
886 i >= 0 && (errmsg[i] == '\n' || errmsg[i] == '\r'); i--) {
887 errmsg[i] = '\0';
888 }
889
890 return errmsg;
891 } else {
892 // FormatMessage failed
893 return "Unknown error";
894 }
895}
896
897
Bert Belder6ee73a22011-11-04 15:10:48898Local<Value> WinapiErrnoException(int errorno,
Bert Belder829735e2011-11-04 15:23:02899 const char* syscall,
900 const char* msg,
901 const char* path) {
Bert Belder6ee73a22011-11-04 15:10:48902 Local<Value> e;
Bert Belder829735e2011-11-04 15:23:02903 if (!msg || !msg[0]) {
Bert Belder6ee73a22011-11-04 15:10:48904 msg = winapi_strerror(errorno);
905 }
906 Local<String> message = String::NewSymbol(msg);
907
908 if (syscall_symbol.IsEmpty()) {
909 syscall_symbol = NODE_PSYMBOL("syscall");
910 errno_symbol = NODE_PSYMBOL("errno");
911 errpath_symbol = NODE_PSYMBOL("path");
912 code_symbol = NODE_PSYMBOL("code");
913 }
914
915 if (path) {
916 Local<String> cons1 = String::Concat(message, String::NewSymbol(" '"));
917 Local<String> cons2 = String::Concat(cons1, String::New(path));
918 Local<String> cons3 = String::Concat(cons2, String::NewSymbol("'"));
919 e = Exception::Error(cons3);
920 } else {
921 e = Exception::Error(message);
922 }
923
924 Local<Object> obj = e->ToObject();
925
926 obj->Set(errno_symbol, Integer::New(errorno));
927 if (path) obj->Set(errpath_symbol, String::New(path));
928 if (syscall) obj->Set(syscall_symbol, String::NewSymbol(syscall));
929 return e;
930}
931#endif
932
933
Ben Noordhuis55c65cc2010-09-24 15:02:08934Handle<Value> FromConstructorTemplate(Persistent<FunctionTemplate>& t,
935 const Arguments& args) {
936 HandleScope scope;
937
938 const int argc = args.Length();
Ryan Dahl5dd08c62010-10-09 21:21:26939 Local<Value>* argv = new Local<Value>[argc];
Ben Noordhuis55c65cc2010-09-24 15:02:08940
941 for (int i = 0; i < argc; ++i) {
942 argv[i] = args[i];
943 }
944
945 Local<Object> instance = t->GetFunction()->NewInstance(argc, argv);
Ryan Dahl5dd08c62010-10-09 21:21:26946
947 delete[] argv;
948
Ben Noordhuis55c65cc2010-09-24 15:02:08949 return scope.Close(instance);
950}
951
952
Ryan Dahl650a3082011-05-28 20:44:03953// MakeCallback may only be made directly off the event loop.
954// That is there can be no JavaScript stack frames underneath it.
955// (Is there any way to assert that?)
956//
957// Maybe make this a method of a node::Handle super class
958//
959void MakeCallback(Handle<Object> object,
960 const char* method,
961 int argc,
962 Handle<Value> argv[]) {
963 HandleScope scope;
964
Bert Belder889620d2011-10-28 09:34:53965 Local<Value> callback_v = object->Get(String::New(method));
Ryan Dahl26c59052011-10-07 07:57:37966 if (!callback_v->IsFunction()) {
967 fprintf(stderr, "method = %s", method);
968 }
Ryan Dahl650a3082011-05-28 20:44:03969 assert(callback_v->IsFunction());
970 Local<Function> callback = Local<Function>::Cast(callback_v);
971
972 // TODO Hook for long stack traces to be made here.
973
974 TryCatch try_catch;
975
976 callback->Call(object, argc, argv);
977
978 if (try_catch.HasCaught()) {
979 FatalException(try_catch);
980 }
981}
982
983
Ryan Dahl6cc42922011-10-19 23:53:07984void SetErrno(uv_err_t err) {
985 HandleScope scope;
986
987 if (errno_symbol.IsEmpty()) {
988 errno_symbol = NODE_PSYMBOL("errno");
989 }
990
991 if (err.code == UV_UNKNOWN) {
992 char errno_buf[100];
993 snprintf(errno_buf, 100, "Unknown system errno %d", err.sys_errno_);
994 Context::GetCurrent()->Global()->Set(errno_symbol, String::New(errno_buf));
995 } else {
996 Context::GetCurrent()->Global()->Set(errno_symbol,
997 String::NewSymbol(uv_err_name(err)));
998 }
Ryan Dahl650a3082011-05-28 20:44:03999}
1000
1001
Ryan Dahl07792af2009-09-21 10:27:221002enum encoding ParseEncoding(Handle<Value> encoding_v, enum encoding _default) {
1003 HandleScope scope;
1004
1005 if (!encoding_v->IsString()) return _default;
1006
1007 String::Utf8Value encoding(encoding_v->ToString());
1008
1009 if (strcasecmp(*encoding, "utf8") == 0) {
1010 return UTF8;
Ryan Dahl2b994d92009-10-06 08:45:181011 } else if (strcasecmp(*encoding, "utf-8") == 0) {
1012 return UTF8;
Ryan Dahl07792af2009-09-21 10:27:221013 } else if (strcasecmp(*encoding, "ascii") == 0) {
1014 return ASCII;
Ben Noordhuis95638c92010-07-28 12:20:231015 } else if (strcasecmp(*encoding, "base64") == 0) {
1016 return BASE64;
Konstantin Käfer9e101f22011-02-06 20:49:521017 } else if (strcasecmp(*encoding, "ucs2") == 0) {
1018 return UCS2;
1019 } else if (strcasecmp(*encoding, "ucs-2") == 0) {
1020 return UCS2;
Ryan Dahl07792af2009-09-21 10:27:221021 } else if (strcasecmp(*encoding, "binary") == 0) {
1022 return BINARY;
isaacs0aa1a8a2011-02-20 01:29:011023 } else if (strcasecmp(*encoding, "hex") == 0) {
1024 return HEX;
Ryan Dahl07792af2009-09-21 10:27:221025 } else if (strcasecmp(*encoding, "raw") == 0) {
1026 fprintf(stderr, "'raw' (array of integers) has been removed. "
1027 "Use 'binary'.\n");
1028 return BINARY;
1029 } else if (strcasecmp(*encoding, "raws") == 0) {
1030 fprintf(stderr, "'raws' encoding has been renamed to 'binary'. "
1031 "Please update your code.\n");
1032 return BINARY;
1033 } else {
1034 return _default;
1035 }
1036}
1037
Ryand6c9d312009-09-11 14:02:291038Local<Value> Encode(const void *buf, size_t len, enum encoding encoding) {
Ryan21a1b042009-09-09 13:51:491039 HandleScope scope;
1040
Ryan Dahl46ebaa02010-02-22 20:07:071041 if (!len) return scope.Close(String::Empty());
Ryan21a1b042009-09-09 13:51:491042
Ryan Dahl07792af2009-09-21 10:27:221043 if (encoding == BINARY) {
Ryan88900702009-09-09 15:22:201044 const unsigned char *cbuf = static_cast<const unsigned char*>(buf);
Ryand6c9d312009-09-11 14:02:291045 uint16_t * twobytebuf = new uint16_t[len];
Ryan88900702009-09-09 15:22:201046 for (size_t i = 0; i < len; i++) {
Ryand6c9d312009-09-11 14:02:291047 // XXX is the following line platform independent?
Ryan88900702009-09-09 15:22:201048 twobytebuf[i] = cbuf[i];
1049 }
1050 Local<String> chunk = String::New(twobytebuf, len);
Ryan Dahl663deb32009-09-22 16:35:151051 delete [] twobytebuf; // TODO use ExternalTwoByteString?
Ryan88900702009-09-09 15:22:201052 return scope.Close(chunk);
1053 }
1054
Ryan21a1b042009-09-09 13:51:491055 // utf8 or ascii encoding
1056 Local<String> chunk = String::New((const char*)buf, len);
1057 return scope.Close(chunk);
1058}
1059
Ryand6c9d312009-09-11 14:02:291060// Returns -1 if the handle was not valid for decoding
1061ssize_t DecodeBytes(v8::Handle<v8::Value> val, enum encoding encoding) {
Ryan21a1b042009-09-09 13:51:491062 HandleScope scope;
1063
1064 if (val->IsArray()) {
Ryan Dahl07792af2009-09-21 10:27:221065 fprintf(stderr, "'raw' encoding (array of integers) has been removed. "
1066 "Use 'binary'.\n");
1067 assert(0);
1068 return -1;
Ryan21a1b042009-09-09 13:51:491069 }
1070
Ben Noordhuis9a79bb62012-01-08 23:45:191071 if (encoding == BINARY && Buffer::HasInstance(val)) {
1072 return Buffer::Length(val->ToObject());
1073 }
1074
Ryan Dahl07792af2009-09-21 10:27:221075 Local<String> str = val->ToString();
Ryan21a1b042009-09-09 13:51:491076
Ryand6c9d312009-09-11 14:02:291077 if (encoding == UTF8) return str->Utf8Length();
Konstantin Käfer9e101f22011-02-06 20:49:521078 else if (encoding == UCS2) return str->Length() * 2;
isaacs0aa1a8a2011-02-20 01:29:011079 else if (encoding == HEX) return str->Length() / 2;
Ryan21a1b042009-09-09 13:51:491080
Ryand6c9d312009-09-11 14:02:291081 return str->Length();
Ryan21a1b042009-09-09 13:51:491082}
1083
1084#ifndef MIN
Ryand6c9d312009-09-11 14:02:291085# define MIN(a, b) ((a) < (b) ? (a) : (b))
Ryan21a1b042009-09-09 13:51:491086#endif
1087
1088// Returns number of bytes written.
Ryan Dahl53530e92010-04-02 21:55:281089ssize_t DecodeWrite(char *buf,
1090 size_t buflen,
Ryand6c9d312009-09-11 14:02:291091 v8::Handle<v8::Value> val,
1092 enum encoding encoding) {
Ryan21a1b042009-09-09 13:51:491093 HandleScope scope;
1094
1095 // XXX
1096 // A lot of improvement can be made here. See:
1097 // http://code.google.com/p/v8/issues/detail?id=270
1098 // http://groups.google.com/group/v8-dev/browse_thread/thread/dba28a81d9215291/ece2b50a3b4022c
1099 // http://groups.google.com/group/v8-users/browse_thread/thread/1f83b0ba1f0a611
1100
1101 if (val->IsArray()) {
Ryan Dahl07792af2009-09-21 10:27:221102 fprintf(stderr, "'raw' encoding (array of integers) has been removed. "
1103 "Use 'binary'.\n");
1104 assert(0);
1105 return -1;
Ryan21a1b042009-09-09 13:51:491106 }
1107
Ryan Dahl07792af2009-09-21 10:27:221108 Local<String> str = val->ToString();
Ryan21a1b042009-09-09 13:51:491109
1110 if (encoding == UTF8) {
Ryan Dahl41ef1712010-04-14 17:34:171111 str->WriteUtf8(buf, buflen, NULL, String::HINT_MANY_WRITES_EXPECTED);
Ryan21a1b042009-09-09 13:51:491112 return buflen;
1113 }
1114
Ryan88900702009-09-09 15:22:201115 if (encoding == ASCII) {
Ryan Dahl41ef1712010-04-14 17:34:171116 str->WriteAscii(buf, 0, buflen, String::HINT_MANY_WRITES_EXPECTED);
Ryan88900702009-09-09 15:22:201117 return buflen;
1118 }
1119
1120 // THIS IS AWFUL!!! FIXME
1121
Ryan Dahl07792af2009-09-21 10:27:221122 assert(encoding == BINARY);
1123
Ryand6c9d312009-09-11 14:02:291124 uint16_t * twobytebuf = new uint16_t[buflen];
Ryan88900702009-09-09 15:22:201125
Ryan Dahl41ef1712010-04-14 17:34:171126 str->Write(twobytebuf, 0, buflen, String::HINT_MANY_WRITES_EXPECTED);
Ryan88900702009-09-09 15:22:201127
1128 for (size_t i = 0; i < buflen; i++) {
1129 unsigned char *b = reinterpret_cast<unsigned char*>(&twobytebuf[i]);
Ryan88900702009-09-09 15:22:201130 buf[i] = b[0];
1131 }
1132
Ryan Dahl663deb32009-09-22 16:35:151133 delete [] twobytebuf;
Ryand6c9d312009-09-11 14:02:291134
Ryan21a1b042009-09-09 13:51:491135 return buflen;
1136}
1137
Ryan5131e0a2009-03-09 00:23:411138
Ryan Dahlb57c1f52010-11-24 02:46:131139void DisplayExceptionLine (TryCatch &try_catch) {
1140 HandleScope scope;
1141
Ryan Dahlb20c3432010-02-12 05:55:081142 Handle<Message> message = try_catch.Message();
Ryan Dahlef300d12009-09-13 15:43:191143
Ryan Dahlcdf5d912011-10-11 20:41:331144 uv_tty_reset_mode();
1145
Ryan Dahlb3c03592010-07-27 02:08:211146 fprintf(stderr, "\n");
Ryan Dahl41f213b2010-05-31 18:50:351147
Ryan Dahlb57c1f52010-11-24 02:46:131148 if (!message.IsEmpty()) {
Ryan Dahl53a841d2009-12-29 19:20:511149 // Print (filename):(line number): (message).
1150 String::Utf8Value filename(message->GetScriptResourceName());
Ryan Dahlb57c1f52010-11-24 02:46:131151 const char* filename_string = *filename;
Ryan Dahl53a841d2009-12-29 19:20:511152 int linenum = message->GetLineNumber();
1153 fprintf(stderr, "%s:%i\n", filename_string, linenum);
1154 // Print line of source code.
1155 String::Utf8Value sourceline(message->GetSourceLine());
Ryan Dahlb57c1f52010-11-24 02:46:131156 const char* sourceline_string = *sourceline;
Ryan Dahlab068db2010-05-09 20:54:581157
1158 // HACK HACK HACK
1159 //
1160 // FIXME
1161 //
1162 // Because of how CommonJS modules work, all scripts are wrapped with a
1163 // "function (function (exports, __filename, ...) {"
1164 // to provide script local variables.
1165 //
1166 // When reporting errors on the first line of a script, this wrapper
1167 // function is leaked to the user. This HACK is to remove it. The length
isaacs703a1ff2011-07-29 18:56:051168 // of the wrapper is 62. That wrapper is defined in src/node.js
Ryan Dahlab068db2010-05-09 20:54:581169 //
1170 // If that wrapper is ever changed, then this number also has to be
1171 // updated. Or - someone could clean this up so that the two peices
1172 // don't need to be changed.
1173 //
1174 // Even better would be to get support into V8 for wrappers that
1175 // shouldn't be reported to users.
isaacs703a1ff2011-07-29 18:56:051176 int offset = linenum == 1 ? 62 : 0;
Ryan Dahlab068db2010-05-09 20:54:581177
1178 fprintf(stderr, "%s\n", sourceline_string + offset);
Ryan Dahl53a841d2009-12-29 19:20:511179 // Print wavy underline (GetUnderline is deprecated).
1180 int start = message->GetStartColumn();
Ryan Dahlab068db2010-05-09 20:54:581181 for (int i = offset; i < start; i++) {
Ryan Dahl53a841d2009-12-29 19:20:511182 fprintf(stderr, " ");
1183 }
1184 int end = message->GetEndColumn();
1185 for (int i = start; i < end; i++) {
1186 fprintf(stderr, "^");
1187 }
1188 fprintf(stderr, "\n");
Ryan Dahl8e6dd522010-01-15 18:45:041189 }
Ryan Dahlb57c1f52010-11-24 02:46:131190}
1191
1192
1193static void ReportException(TryCatch &try_catch, bool show_line) {
1194 HandleScope scope;
1195 Handle<Message> message = try_catch.Message();
1196
1197 if (show_line) DisplayExceptionLine(try_catch);
Ryan Dahl53a841d2009-12-29 19:20:511198
Ryan Dahlda932302010-05-14 18:48:141199 String::Utf8Value trace(try_catch.StackTrace());
1200
isaacs8df6f9e2011-04-25 19:22:181201 // range errors have a trace member set to undefined
1202 if (trace.length() > 0 && !try_catch.StackTrace()->IsUndefined()) {
Ryanafd9e712009-08-31 16:22:091203 fprintf(stderr, "%s\n", *trace);
isaacse9b6b0b2010-10-02 06:22:341204 } else {
1205 // this really only happens for RangeErrors, since they're the only
isaacs8df6f9e2011-04-25 19:22:181206 // kind that won't have all this info in the trace, or when non-Error
1207 // objects are thrown manually.
isaacse9b6b0b2010-10-02 06:22:341208 Local<Value> er = try_catch.Exception();
isaacs8df6f9e2011-04-25 19:22:181209 bool isErrorObject = er->IsObject() &&
1210 !(er->ToObject()->Get(String::New("message"))->IsUndefined()) &&
1211 !(er->ToObject()->Get(String::New("name"))->IsUndefined());
1212
1213 if (isErrorObject) {
1214 String::Utf8Value name(er->ToObject()->Get(String::New("name")));
1215 fprintf(stderr, "%s: ", *name);
1216 }
1217
1218 String::Utf8Value msg(!isErrorObject ? er->ToString()
isaacse9b6b0b2010-10-02 06:22:341219 : er->ToObject()->Get(String::New("message"))->ToString());
1220 fprintf(stderr, "%s\n", *msg);
Ryan5131e0a2009-03-09 00:23:411221 }
isaacse9b6b0b2010-10-02 06:22:341222
Ryand7e220c2009-09-09 20:35:401223 fflush(stderr);
Ryan5131e0a2009-03-09 00:23:411224}
1225
Ryand6c9d312009-09-11 14:02:291226// Executes a str within the current v8 context.
Tom Hughes74954ce2011-03-08 06:00:511227Local<Value> ExecuteString(Handle<String> source, Handle<Value> filename) {
Ryan63a9cd32009-04-15 08:08:281228 HandleScope scope;
Ryan408526a2009-04-21 11:52:211229 TryCatch try_catch;
1230
Herbert Vojcikc2a06722010-04-17 15:18:151231 Local<v8::Script> script = v8::Script::Compile(source, filename);
Ryan63a9cd32009-04-15 08:08:281232 if (script.IsEmpty()) {
Ryan Dahlab068db2010-05-09 20:54:581233 ReportException(try_catch, true);
Ryan34a6f102009-05-28 12:47:161234 exit(1);
Ryan63a9cd32009-04-15 08:08:281235 }
1236
Ryan Dahl9f5643f2010-01-31 07:22:341237 Local<Value> result = script->Run();
Ryan63a9cd32009-04-15 08:08:281238 if (result.IsEmpty()) {
Ryan Dahlab068db2010-05-09 20:54:581239 ReportException(try_catch, true);
Ryan34a6f102009-05-28 12:47:161240 exit(1);
Ryan63a9cd32009-04-15 08:08:281241 }
1242
1243 return scope.Close(result);
1244}
1245
Felix Geisendörfer7371fcb2009-11-11 17:10:581246
Robert Mustacchi22404862011-12-15 01:02:151247static Handle<Value> Abort(const Arguments& args) {
1248 abort();
Igor Zinkovsky88cc6882011-12-16 01:18:281249 return Undefined();
Robert Mustacchi22404862011-12-15 01:02:151250}
1251
1252
Brandon Beacher47fcf782009-11-03 18:13:381253static Handle<Value> Chdir(const Arguments& args) {
1254 HandleScope scope;
Ryan Dahlb20c3432010-02-12 05:55:081255
Brandon Beacher47fcf782009-11-03 18:13:381256 if (args.Length() != 1 || !args[0]->IsString()) {
1257 return ThrowException(Exception::Error(String::New("Bad argument.")));
1258 }
Ryan Dahlb20c3432010-02-12 05:55:081259
Brandon Beacher47fcf782009-11-03 18:13:381260 String::Utf8Value path(args[0]->ToString());
Ryan Dahlb20c3432010-02-12 05:55:081261
Bert Beldere84edd22011-12-01 23:24:441262 uv_err_t r = uv_chdir(*path);
Ryan Dahlb20c3432010-02-12 05:55:081263
Bert Beldere84edd22011-12-01 23:24:441264 if (r.code != UV_OK) {
1265 return ThrowException(UVException(r.code, "uv_chdir"));
Brandon Beacher47fcf782009-11-03 18:13:381266 }
1267
1268 return Undefined();
1269}
1270
Bert Beldercbcf4fe2011-11-24 01:19:541271
Ryand6c9d312009-09-11 14:02:291272static Handle<Value> Cwd(const Arguments& args) {
Michael Carter8ea6adc2009-09-01 09:39:301273 HandleScope scope;
Bert Beldere84edd22011-12-01 23:24:441274#ifdef _WIN32
1275 /* MAX_PATH is in characters, not bytes. Make sure we have enough headroom. */
1276 char buf[MAX_PATH * 4 + 1];
1277#else
1278 char buf[PATH_MAX + 1];
1279#endif
Michael Carter8ea6adc2009-09-01 09:39:301280
Bert Beldere84edd22011-12-01 23:24:441281 uv_err_t r = uv_cwd(buf, ARRAY_SIZE(buf) - 1);
1282 if (r.code != UV_OK) {
1283 return ThrowException(UVException(r.code, "uv_cwd"));
Michael Carter8ea6adc2009-09-01 09:39:301284 }
Peter Griess4e3c5d82010-07-12 15:47:451285
Bert Beldere84edd22011-12-01 23:24:441286 buf[ARRAY_SIZE(buf) - 1] = '\0';
1287 Local<String> cwd = String::New(buf);
Michael Carter8ea6adc2009-09-01 09:39:301288
1289 return scope.Close(cwd);
1290}
1291
Bert Beldere84edd22011-12-01 23:24:441292
Bert Belder86fba382011-11-24 01:38:341293#ifdef _WIN32
1294static Handle<Value> CwdForDrive(const Arguments& args) {
1295 HandleScope scope;
1296
1297 if (args.Length() < 1) {
1298 Local<Value> exception = Exception::Error(
1299 String::New("process._cwdForDrive takes exactly 1 argument."));
1300 return ThrowException(exception);
1301 }
1302
1303 Local<String> driveLetter = args[0]->ToString();
1304 if (driveLetter->Length() != 1) {
1305 Local<Value> exception = Exception::Error(
1306 String::New("Drive name should be 1 character."));
1307 return ThrowException(exception);
1308 }
1309
1310 char drive;
1311
1312 driveLetter->WriteAscii(&drive, 0, 1, 0);
1313 if (drive >= 'a' && drive <= 'z') {
1314 // Convert to uppercase
1315 drive += 'A' - 'a';
1316 } else if (drive < 'A' || drive > 'Z') {
1317 // Not a letter
1318 Local<Value> exception = Exception::Error(
1319 String::New("Drive name should be a letter."));
1320 return ThrowException(exception);
1321 }
1322
1323 WCHAR env_key[] = L"=X:";
1324 env_key[1] = (WCHAR) drive;
1325
1326 DWORD len = GetEnvironmentVariableW(env_key, NULL, 0);
1327 if (len == 0 && GetLastError() == ERROR_ENVVAR_NOT_FOUND) {
1328 // There is no current directory for that drive. Default to drive + ":\".
1329 Local<String> cwd = String::Concat(String::New(&drive, 1),
1330 String::New(":\\"));
1331 return scope.Close(cwd);
1332
1333 } else if (len == 0) {
1334 // Error
1335 Local<Value> exception = Exception::Error(
1336 String::New(winapi_strerror(GetLastError())));
1337 return ThrowException(exception);
1338 }
1339
1340 WCHAR* buffer = new WCHAR[len];
1341 if (buffer == NULL) {
1342 Local<Value> exception = Exception::Error(
1343 String::New("Out of memory."));
1344 return ThrowException(exception);
1345 }
1346
1347 DWORD len2 = GetEnvironmentVariableW(env_key, buffer, len);
1348 if (len2 == 0 || len2 >= len) {
1349 // Error
1350 delete[] buffer;
1351 Local<Value> exception = Exception::Error(
1352 String::New(winapi_strerror(GetLastError())));
1353 return ThrowException(exception);
1354 }
1355
1356 Local<String> cwd = String::New(reinterpret_cast<uint16_t*>(buffer), len2);
1357 delete[] buffer;
1358 return scope.Close(cwd);
1359}
1360#endif
1361
1362
Ryan Dahlacc120a2011-08-09 20:53:561363static Handle<Value> Umask(const Arguments& args) {
Friedemann Altrock0433d822009-11-22 18:52:521364 HandleScope scope;
Rasmus Andersson374300c2010-02-27 17:18:411365 unsigned int old;
isaacs5f2e9092011-01-25 18:40:121366
Ryan Dahlacc120a2011-08-09 20:53:561367 if (args.Length() < 1 || args[0]->IsUndefined()) {
Rasmus Andersson374300c2010-02-27 17:18:411368 old = umask(0);
1369 umask((mode_t)old);
isaacs5f2e9092011-01-25 18:40:121370
1371 } else if(!args[0]->IsInt32() && !args[0]->IsString()) {
Friedemann Altrock0433d822009-11-22 18:52:521372 return ThrowException(Exception::TypeError(
isaacs5f2e9092011-01-25 18:40:121373 String::New("argument must be an integer or octal string.")));
1374
1375 } else {
1376 int oct;
1377 if(args[0]->IsInt32()) {
1378 oct = args[0]->Uint32Value();
1379 } else {
1380 oct = 0;
1381 String::Utf8Value str(args[0]);
1382
1383 // Parse the octal string.
1384 for (int i = 0; i < str.length(); i++) {
1385 char c = (*str)[i];
1386 if (c > '7' || c < '0') {
1387 return ThrowException(Exception::TypeError(
1388 String::New("invalid octal string")));
1389 }
1390 oct *= 8;
1391 oct += c - '0';
1392 }
1393 }
1394 old = umask(static_cast<mode_t>(oct));
Friedemann Altrock0433d822009-11-22 18:52:521395 }
isaacs5f2e9092011-01-25 18:40:121396
Friedemann Altrock0433d822009-11-22 18:52:521397 return scope.Close(Uint32::New(old));
1398}
1399
Michael Cartera3860762010-02-08 06:13:101400
Ryan Dahlacc120a2011-08-09 20:53:561401#ifdef __POSIX__
1402
Michael Cartera3860762010-02-08 06:13:101403static Handle<Value> GetUid(const Arguments& args) {
1404 HandleScope scope;
Ryan Dahl39943402010-03-15 19:49:401405 assert(args.Length() == 0);
Michael Cartera3860762010-02-08 06:13:101406 int uid = getuid();
1407 return scope.Close(Integer::New(uid));
1408}
1409
Ryan Dahlacc120a2011-08-09 20:53:561410
James Duncandf1c1e52010-02-23 22:45:021411static Handle<Value> GetGid(const Arguments& args) {
1412 HandleScope scope;
Ryan Dahl39943402010-03-15 19:49:401413 assert(args.Length() == 0);
James Duncandf1c1e52010-02-23 22:45:021414 int gid = getgid();
1415 return scope.Close(Integer::New(gid));
1416}
1417
1418
1419static Handle<Value> SetGid(const Arguments& args) {
1420 HandleScope scope;
Ryan Dahl39943402010-03-15 19:49:401421
James Duncandf1c1e52010-02-23 22:45:021422 if (args.Length() < 1) {
1423 return ThrowException(Exception::Error(
Ryan Dahl39943402010-03-15 19:49:401424 String::New("setgid requires 1 argument")));
James Duncandf1c1e52010-02-23 22:45:021425 }
1426
Peter Griess2420f072010-05-19 00:40:441427 int gid;
Blake Mizerany8c853402010-06-30 06:12:461428
Peter Griess2420f072010-05-19 00:40:441429 if (args[0]->IsNumber()) {
1430 gid = args[0]->Int32Value();
1431 } else if (args[0]->IsString()) {
1432 String::Utf8Value grpnam(args[0]->ToString());
1433 struct group grp, *grpp = NULL;
1434 int err;
1435
Peter Griess4e3c5d82010-07-12 15:47:451436 if ((err = getgrnam_r(*grpnam, &grp, getbuf, ARRAY_SIZE(getbuf), &grpp)) ||
Peter Griess2420f072010-05-19 00:40:441437 grpp == NULL) {
Brian White52b9ede2011-03-18 05:39:391438 if (errno == 0)
1439 return ThrowException(Exception::Error(
1440 String::New("setgid group id does not exist")));
1441 else
1442 return ThrowException(ErrnoException(errno, "getgrnam_r"));
Peter Griess2420f072010-05-19 00:40:441443 }
1444
1445 gid = grpp->gr_gid;
1446 } else {
1447 return ThrowException(Exception::Error(
1448 String::New("setgid argument must be a number or a string")));
1449 }
1450
James Duncandf1c1e52010-02-23 22:45:021451 int result;
isaacs0dba38e2010-03-03 09:11:471452 if ((result = setgid(gid)) != 0) {
Peter Griess2420f072010-05-19 00:40:441453 return ThrowException(ErrnoException(errno, "setgid"));
James Duncandf1c1e52010-02-23 22:45:021454 }
1455 return Undefined();
1456}
Michael Cartera3860762010-02-08 06:13:101457
Ryan Dahlacc120a2011-08-09 20:53:561458
Michael Cartera3860762010-02-08 06:13:101459static Handle<Value> SetUid(const Arguments& args) {
1460 HandleScope scope;
1461
1462 if (args.Length() < 1) {
1463 return ThrowException(Exception::Error(
1464 String::New("setuid requires 1 argument")));
1465 }
1466
Peter Griess2420f072010-05-19 00:40:441467 int uid;
1468
1469 if (args[0]->IsNumber()) {
1470 uid = args[0]->Int32Value();
1471 } else if (args[0]->IsString()) {
1472 String::Utf8Value pwnam(args[0]->ToString());
1473 struct passwd pwd, *pwdp = NULL;
1474 int err;
1475
Peter Griess4e3c5d82010-07-12 15:47:451476 if ((err = getpwnam_r(*pwnam, &pwd, getbuf, ARRAY_SIZE(getbuf), &pwdp)) ||
Peter Griess2420f072010-05-19 00:40:441477 pwdp == NULL) {
Brian White52b9ede2011-03-18 05:39:391478 if (errno == 0)
1479 return ThrowException(Exception::Error(
1480 String::New("setuid user id does not exist")));
1481 else
1482 return ThrowException(ErrnoException(errno, "getpwnam_r"));
Peter Griess2420f072010-05-19 00:40:441483 }
1484
1485 uid = pwdp->pw_uid;
1486 } else {
1487 return ThrowException(Exception::Error(
1488 String::New("setuid argument must be a number or a string")));
1489 }
1490
Michael Cartera3860762010-02-08 06:13:101491 int result;
1492 if ((result = setuid(uid)) != 0) {
Peter Griess2420f072010-05-19 00:40:441493 return ThrowException(ErrnoException(errno, "setuid"));
Michael Cartera3860762010-02-08 06:13:101494 }
1495 return Undefined();
1496}
1497
Ryan Dahlacc120a2011-08-09 20:53:561498
Bert Belder30bab522010-11-25 00:09:061499#endif // __POSIX__
1500
Michael Cartera3860762010-02-08 06:13:101501
Ryand6c9d312009-09-11 14:02:291502v8::Handle<v8::Value> Exit(const v8::Arguments& args) {
Ryan Dahl6f92d8f2010-02-08 05:59:561503 HandleScope scope;
Ryan Dahl6f92d8f2010-02-08 05:59:561504 exit(args[0]->IntegerValue());
Ryan116f4de2009-08-26 20:03:191505 return Undefined();
Ryan0f517032009-04-29 09:09:321506}
1507
Ryan Dahl3ac6dee2010-05-08 02:05:591508
Ryan Dahlf657d582011-06-22 12:06:261509static void CheckStatus(uv_timer_t* watcher, int status) {
1510 assert(watcher == &gc_timer);
Ryan Dahl3ac6dee2010-05-08 02:05:591511
Ryan Dahl3ac6dee2010-05-08 02:05:591512 // check memory
Ryan Dahl7a5977b2011-06-07 16:37:271513 if (!uv_is_active((uv_handle_t*) &gc_idle)) {
Ryan Dahlaeed9662011-03-18 18:39:441514 HeapStatistics stats;
1515 V8::GetHeapStatistics(&stats);
1516 if (stats.total_heap_size() > 1024 * 1024 * 128) {
Ryan Dahl3ac6dee2010-05-08 02:05:591517 // larger than 128 megs, just start the idle watcher
Ryan Dahl7547c7d2011-12-07 01:00:331518 uv_idle_start(&gc_idle, node::Idle);
Ryan Dahl3ac6dee2010-05-08 02:05:591519 return;
1520 }
1521 }
Ryan Dahl3ac6dee2010-05-08 02:05:591522
Ben Noordhuis74a82152012-02-03 15:32:001523 double d = uv_now(uv_default_loop()) - TICK_TIME(3);
Ryan Dahl3ac6dee2010-05-08 02:05:591524
1525 //printfb("timer d = %f\n", d);
1526
1527 if (d >= GC_WAIT_TIME - 1.) {
1528 //fprintf(stderr, "start idle\n");
Ryan Dahl7547c7d2011-12-07 01:00:331529 uv_idle_start(&gc_idle, node::Idle);
Ryan Dahl3ac6dee2010-05-08 02:05:591530 }
1531}
1532
Igor Zinkovsky500c8f42011-12-15 20:36:051533
Tom Hughescf78ce52011-03-04 23:57:541534static Handle<Value> Uptime(const Arguments& args) {
1535 HandleScope scope;
1536 assert(args.Length() == 0);
Igor Zinkovsky500c8f42011-12-15 20:36:051537 double uptime;
Tom Hughescf78ce52011-03-04 23:57:541538
Igor Zinkovsky500c8f42011-12-15 20:36:051539 uv_err_t err = uv_uptime(&uptime);
Tom Hughescf78ce52011-03-04 23:57:541540
Igor Zinkovsky500c8f42011-12-15 20:36:051541 if (err.code != UV_OK) {
Tom Hughescf78ce52011-03-04 23:57:541542 return Undefined();
1543 }
1544
Igor Zinkovsky500c8f42011-12-15 20:36:051545 return scope.Close(Number::New(uptime - prog_start_time));
Tom Hughescf78ce52011-03-04 23:57:541546}
Ryan Dahl3ac6dee2010-05-08 02:05:591547
Ryan Dahlc344fbc2011-10-06 21:59:381548
1549v8::Handle<v8::Value> UVCounters(const v8::Arguments& args) {
1550 HandleScope scope;
1551
Ben Noordhuis74a82152012-02-03 15:32:001552 uv_counters_t* c = &uv_default_loop()->counters;
Ryan Dahlc344fbc2011-10-06 21:59:381553
1554 Local<Object> obj = Object::New();
1555
Bert Belder889620d2011-10-28 09:34:531556#define setc(name) \
1557 obj->Set(String::New(#name), Integer::New(static_cast<int32_t>(c->name)));
Ryan Dahlc344fbc2011-10-06 21:59:381558
1559 setc(eio_init)
1560 setc(req_init)
1561 setc(handle_init)
1562 setc(stream_init)
1563 setc(tcp_init)
1564 setc(udp_init)
1565 setc(pipe_init)
1566 setc(tty_init)
1567 setc(prepare_init)
1568 setc(check_init)
1569 setc(idle_init)
1570 setc(async_init)
1571 setc(timer_init)
1572 setc(process_init)
1573 setc(fs_event_init)
1574
1575#undef setc
1576
1577 return scope.Close(obj);
1578}
1579
1580
Ryan Dahlb3b3cfe2009-11-03 12:00:421581v8::Handle<v8::Value> MemoryUsage(const v8::Arguments& args) {
1582 HandleScope scope;
Ryan Dahl39943402010-03-15 19:49:401583 assert(args.Length() == 0);
Ryan Dahlb3b3cfe2009-11-03 12:00:421584
Ryan Dahl5783a522011-10-18 21:30:311585 size_t rss;
Ryan Dahlb3b3cfe2009-11-03 12:00:421586
Igor Zinkovsky500c8f42011-12-15 20:36:051587 uv_err_t err = uv_resident_set_memory(&rss);
Ryan Dahlb3b3cfe2009-11-03 12:00:421588
Igor Zinkovsky500c8f42011-12-15 20:36:051589 if (err.code != UV_OK) {
1590 return ThrowException(UVException(err.code, "uv_resident_set_memory"));
Ryan Dahl3a701292009-11-03 00:30:011591 }
1592
Ryan Dahl3a701292009-11-03 00:30:011593 Local<Object> info = Object::New();
1594
Ryan Dahl45a806a2009-12-09 08:02:211595 if (rss_symbol.IsEmpty()) {
1596 rss_symbol = NODE_PSYMBOL("rss");
Ryan Dahl45a806a2009-12-09 08:02:211597 heap_total_symbol = NODE_PSYMBOL("heapTotal");
1598 heap_used_symbol = NODE_PSYMBOL("heapUsed");
1599 }
1600
Russ Bradberry754e23d2011-11-29 22:28:221601 info->Set(rss_symbol, Number::New(rss));
Ryan Dahl3a701292009-11-03 00:30:011602
Ryan Dahl38e425d2009-11-28 15:31:291603 // V8 memory usage
1604 HeapStatistics v8_heap_stats;
1605 V8::GetHeapStatistics(&v8_heap_stats);
Ryan Dahl45a806a2009-12-09 08:02:211606 info->Set(heap_total_symbol,
Ryan Dahl38e425d2009-11-28 15:31:291607 Integer::NewFromUnsigned(v8_heap_stats.total_heap_size()));
Ryan Dahl45a806a2009-12-09 08:02:211608 info->Set(heap_used_symbol,
Ryan Dahl38e425d2009-11-28 15:31:291609 Integer::NewFromUnsigned(v8_heap_stats.used_heap_size()));
1610
Ryan Dahl3a701292009-11-03 00:30:011611 return scope.Close(info);
1612}
Ryan Dahlb3b3cfe2009-11-03 12:00:421613
Bert Belder4a2cb072010-11-29 17:40:141614
Ryan Dahl6eca9482010-09-17 06:13:031615Handle<Value> Kill(const Arguments& args) {
Brandon Beacher334d56d2009-10-14 21:56:121616 HandleScope scope;
Ryan Dahlb20c3432010-02-12 05:55:081617
Ryan Dahl4227e9d2010-12-21 23:40:101618 if (args.Length() != 2) {
Brandon Beacher334d56d2009-10-14 21:56:121619 return ThrowException(Exception::Error(String::New("Bad argument.")));
1620 }
Ryan Dahlb20c3432010-02-12 05:55:081621
Igor Zinkovsky24a69d22011-11-02 22:06:481622 int pid = args[0]->IntegerValue();
Ryan Dahl6eca9482010-09-17 06:13:031623 int sig = args[1]->Int32Value();
Igor Zinkovsky24a69d22011-11-02 22:06:481624 uv_err_t err = uv_kill(pid, sig);
Brandon Beacher334d56d2009-10-14 21:56:121625
Igor Zinkovsky24a69d22011-11-02 22:06:481626 if (err.code != UV_OK) {
1627 SetErrno(err);
1628 return scope.Close(Integer::New(-1));
1629 }
Brandon Beacher334d56d2009-10-14 21:56:121630
1631 return Undefined();
1632}
1633
Bert Belderdd93c532011-10-28 10:05:091634
1635typedef void (UV_DYNAMIC* extInit)(Handle<Object> exports);
Ryan2b6d7242009-06-20 13:07:101636
Ryan Dahl38814552009-10-09 15:15:471637// DLOpen is node.dlopen(). Used to load 'module.node' dynamically shared
1638// objects.
Ryand6c9d312009-09-11 14:02:291639Handle<Value> DLOpen(const v8::Arguments& args) {
Ryan2b6d7242009-06-20 13:07:101640 HandleScope scope;
Bert Belderdd93c532011-10-28 10:05:091641 char symbol[1024], *base, *pos;
1642 uv_lib_t lib;
1643 node_module_struct compat_mod;
1644 uv_err_t err;
1645 int r;
Ryan2b6d7242009-06-20 13:07:101646
Bert Belderdd93c532011-10-28 10:05:091647 if (args.Length() < 2) {
Bert Belder35f41822011-11-04 15:11:391648 Local<Value> exception = Exception::Error(
1649 String::New("process.dlopen takes exactly 2 arguments."));
1650 return ThrowException(exception);
Bert Belderdd93c532011-10-28 10:05:091651 }
Ryana97dce72009-08-31 09:14:341652
Ryan Dahl38814552009-10-09 15:15:471653 String::Utf8Value filename(args[0]->ToString()); // Cast
1654 Local<Object> target = args[1]->ToObject(); // Cast
Ryan2b6d7242009-06-20 13:07:101655
Bert Belderdd93c532011-10-28 10:05:091656 err = uv_dlopen(*filename, &lib);
1657 if (err.code != UV_OK) {
Bert Belder35f41822011-11-04 15:11:391658 Local<Value> exception = Exception::Error(
1659 String::Concat(String::New("Unable to load shared library "),
1660 args[0]->ToString()));
1661 return ThrowException(exception);
Ryan2b6d7242009-06-20 13:07:101662 }
1663
Bert Belderdd93c532011-10-28 10:05:091664 String::Utf8Value path(args[0]->ToString());
1665 base = *path;
Paul Querna367b87d2010-07-13 08:33:511666
Bert Belderdd93c532011-10-28 10:05:091667 /* Find the shared library filename within the full path. */
1668#ifdef __POSIX__
1669 pos = strrchr(base, '/');
1670 if (pos != NULL) {
Ben Noordhuisa1fa3ef2011-10-30 16:33:421671 base = pos + 1;
Bert Belderdd93c532011-10-28 10:05:091672 }
1673#else // Windows
1674 for (;;) {
1675 pos = strpbrk(base, "\\/:");
1676 if (pos == NULL) {
1677 break;
Paul Querna367b87d2010-07-13 08:33:511678 }
Bert Belderdd93c532011-10-28 10:05:091679 base = pos + 1;
1680 }
1681#endif
Paul Querna367b87d2010-07-13 08:33:511682
Bert Belderdd93c532011-10-28 10:05:091683 /* Strip the .node extension. */
1684 pos = strrchr(base, '.');
1685 if (pos != NULL) {
1686 *pos = '\0';
1687 }
1688
1689 /* Add the `_module` suffix to the extension name. */
1690 r = snprintf(symbol, sizeof symbol, "%s_module", base);
1691 if (r <= 0 || r >= sizeof symbol) {
Bert Belder35f41822011-11-04 15:11:391692 Local<Value> exception =
1693 Exception::Error(String::New("Out of memory."));
1694 return ThrowException(exception);
Paul Querna367b87d2010-07-13 08:33:511695 }
1696
Ryan Dahl38814552009-10-09 15:15:471697 // Get the init() function from the dynamically shared object.
Bert Belderdd93c532011-10-28 10:05:091698 node_module_struct *mod;
1699 err = uv_dlsym(lib, symbol, reinterpret_cast<void**>(&mod));
Ben Noordhuiseaac8812011-08-13 23:25:391700
Bert Belderdd93c532011-10-28 10:05:091701 if (err.code != UV_OK) {
Paul Querna367b87d2010-07-13 08:33:511702 /* Start Compatibility hack: Remove once everyone is using NODE_MODULE macro */
Ben Noordhuiseaac8812011-08-13 23:25:391703 memset(&compat_mod, 0, sizeof compat_mod);
1704
Paul Querna367b87d2010-07-13 08:33:511705 mod = &compat_mod;
1706 mod->version = NODE_MODULE_VERSION;
1707
Bert Belderdd93c532011-10-28 10:05:091708 err = uv_dlsym(lib, "init", reinterpret_cast<void**>(&mod->register_func));
1709 if (err.code != UV_OK) {
1710 uv_dlclose(lib);
Ben Noordhuis216019b2011-11-27 21:38:541711
1712 const char* message;
1713 if (err.code == UV_ENOENT)
1714 message = "Module entry point not found.";
1715 else
Ben Noordhuis4b455ba2011-12-18 21:27:211716 message = uv_strerror(err);
Ben Noordhuis216019b2011-11-27 21:38:541717
1718 return ThrowException(Exception::Error(String::New(message)));
Paul Querna367b87d2010-07-13 08:33:511719 }
Paul Querna367b87d2010-07-13 08:33:511720 /* End Compatibility hack */
1721 }
1722
1723 if (mod->version != NODE_MODULE_VERSION) {
Bert Belder35f41822011-11-04 15:11:391724 Local<Value> exception = Exception::Error(
1725 String::New("Module version mismatch, refusing to load."));
Ryan3862fda2009-08-31 16:48:471726 return ThrowException(exception);
Ryan2b6d7242009-06-20 13:07:101727 }
Ryan2b6d7242009-06-20 13:07:101728
Ryan Dahl38814552009-10-09 15:15:471729 // Execute the C++ module
Paul Querna367b87d2010-07-13 08:33:511730 mod->register_func(target);
Ryan2b6d7242009-06-20 13:07:101731
Peter Griess4e3c5d82010-07-12 15:47:451732 // Tell coverity that 'handle' should not be freed when we return.
1733 // coverity[leaked_storage]
Ryan2b6d7242009-06-20 13:07:101734 return Undefined();
1735}
1736
Tim-Smartae10a482010-03-12 08:36:001737
Ryand6c9d312009-09-11 14:02:291738static void OnFatalError(const char* location, const char* message) {
Ryan Dahl53a841d2009-12-29 19:20:511739 if (location) {
1740 fprintf(stderr, "FATAL ERROR: %s %s\n", location, message);
1741 } else {
1742 fprintf(stderr, "FATAL ERROR: %s\n", message);
1743 }
Ryan34a6f102009-05-28 12:47:161744 exit(1);
Ryan63a9cd32009-04-15 08:08:281745}
1746
Ben Noordhuis74a82152012-02-03 15:32:001747static int uncaught_exception_counter = 0;
Felix Geisendörfer2b252ac2009-11-14 22:07:541748
Ryand6c9d312009-09-11 14:02:291749void FatalException(TryCatch &try_catch) {
Felix Geisendörfer2b252ac2009-11-14 22:07:541750 HandleScope scope;
1751
1752 // Check if uncaught_exception_counter indicates a recursion
1753 if (uncaught_exception_counter > 0) {
Ryan Dahlab068db2010-05-09 20:54:581754 ReportException(try_catch, true);
Felix Geisendörfer2b252ac2009-11-14 22:07:541755 exit(1);
1756 }
1757
Ryan Dahl45a806a2009-12-09 08:02:211758 if (listeners_symbol.IsEmpty()) {
1759 listeners_symbol = NODE_PSYMBOL("listeners");
1760 uncaught_exception_symbol = NODE_PSYMBOL("uncaughtException");
1761 emit_symbol = NODE_PSYMBOL("emit");
1762 }
1763
1764 Local<Value> listeners_v = process->Get(listeners_symbol);
Felix Geisendörfer2b252ac2009-11-14 22:07:541765 assert(listeners_v->IsFunction());
1766
1767 Local<Function> listeners = Local<Function>::Cast(listeners_v);
1768
Ryan Dahl45a806a2009-12-09 08:02:211769 Local<String> uncaught_exception_symbol_l = Local<String>::New(uncaught_exception_symbol);
1770 Local<Value> argv[1] = { uncaught_exception_symbol_l };
Felix Geisendörfer2b252ac2009-11-14 22:07:541771 Local<Value> ret = listeners->Call(process, 1, argv);
1772
1773 assert(ret->IsArray());
1774
1775 Local<Array> listener_array = Local<Array>::Cast(ret);
1776
1777 uint32_t length = listener_array->Length();
1778 // Report and exit if process has no "uncaughtException" listener
1779 if (length == 0) {
Ryan Dahlab068db2010-05-09 20:54:581780 ReportException(try_catch, true);
Felix Geisendörfer2b252ac2009-11-14 22:07:541781 exit(1);
1782 }
1783
1784 // Otherwise fire the process "uncaughtException" event
Ryan Dahl45a806a2009-12-09 08:02:211785 Local<Value> emit_v = process->Get(emit_symbol);
Felix Geisendörfer2b252ac2009-11-14 22:07:541786 assert(emit_v->IsFunction());
1787
1788 Local<Function> emit = Local<Function>::Cast(emit_v);
1789
1790 Local<Value> error = try_catch.Exception();
Ryan Dahl45a806a2009-12-09 08:02:211791 Local<Value> event_argv[2] = { uncaught_exception_symbol_l, error };
Felix Geisendörfer2b252ac2009-11-14 22:07:541792
1793 uncaught_exception_counter++;
1794 emit->Call(process, 2, event_argv);
1795 // Decrement so we know if the next exception is a recursion or not
1796 uncaught_exception_counter--;
Ryane78917b2009-03-09 13:08:311797}
1798
Ryan0e9e9272009-04-04 14:53:431799
Fedor Indutnyb0388cc2011-12-10 16:52:071800static void DebugBreakMessageHandler(const v8::Debug::Message& message) {
Danny Coatesdc8c0792010-08-01 22:46:481801 // do nothing with debug messages.
1802 // The message handler will get changed by DebuggerAgent::CreateSession in
1803 // debug-agent.cc of v8/src when a new session is created
Zoran Tomicicd98ea702010-02-22 05:15:441804}
1805
Ryan Dahl4ab54762011-03-01 17:59:171806
Ben Noordhuis74a82152012-02-03 15:32:001807Persistent<Object> binding_cache;
1808Persistent<Array> module_load_list;
1809
Ryan Dahl627fb5a2010-03-15 20:48:031810static Handle<Value> Binding(const Arguments& args) {
1811 HandleScope scope;
1812
1813 Local<String> module = args[0]->ToString();
1814 String::Utf8Value module_v(module);
Paul Querna30dadfc2010-07-14 06:22:411815 node_module_struct* modp;
Ryan Dahl627fb5a2010-03-15 20:48:031816
1817 if (binding_cache.IsEmpty()) {
1818 binding_cache = Persistent<Object>::New(Object::New());
1819 }
1820
1821 Local<Object> exports;
1822
Paul Querna30dadfc2010-07-14 06:22:411823 if (binding_cache->Has(module)) {
1824 exports = binding_cache->Get(module)->ToObject();
Ryan Dahlea9ee1f2011-07-28 02:30:321825 return scope.Close(exports);
1826 }
Ryan Dahl6eca9482010-09-17 06:13:031827
Ryan Dahlea9ee1f2011-07-28 02:30:321828 // Append a string to process.moduleLoadList
1829 char buf[1024];
1830 snprintf(buf, 1024, "Binding %s", *module_v);
1831 uint32_t l = module_load_list->Length();
1832 module_load_list->Set(l, String::New(buf));
1833
1834 if ((modp = get_builtin_module(*module_v)) != NULL) {
Paul Querna30dadfc2010-07-14 06:22:411835 exports = Object::New();
1836 modp->register_func(exports);
1837 binding_cache->Set(module, exports);
Ryan Dahl6eca9482010-09-17 06:13:031838
1839 } else if (!strcmp(*module_v, "constants")) {
1840 exports = Object::New();
1841 DefineConstants(exports);
1842 binding_cache->Set(module, exports);
1843
Igor Zinkovskyf35a3962011-10-28 22:34:241844#ifdef __POSIX__
1845 } else if (!strcmp(*module_v, "io_watcher")) {
1846 exports = Object::New();
1847 IOWatcher::Initialize(exports);
1848 binding_cache->Set(module, exports);
1849#endif
1850
Ryan Dahlc90546f2010-03-15 21:22:501851 } else if (!strcmp(*module_v, "natives")) {
Paul Querna8dbfe5e2010-07-14 06:32:381852 exports = Object::New();
Ryan Dahlc4636a52010-10-12 18:49:411853 DefineJavaScript(exports);
Paul Querna8dbfe5e2010-07-14 06:32:381854 binding_cache->Set(module, exports);
Ryan Dahlc4636a52010-10-12 18:49:411855
Ryan Dahl627fb5a2010-03-15 20:48:031856 } else {
Ryan Dahl6eca9482010-09-17 06:13:031857
Ryan Dahl627fb5a2010-03-15 20:48:031858 return ThrowException(Exception::Error(String::New("No such module")));
1859 }
1860
1861 return scope.Close(exports);
1862}
1863
Ryan Dahle742d072009-10-09 11:25:041864
Ryan Dahl5185c152010-06-18 07:26:491865static Handle<Value> ProcessTitleGetter(Local<String> property,
1866 const AccessorInfo& info) {
1867 HandleScope scope;
Igor Zinkovsky500c8f42011-12-15 20:36:051868 char buffer[512];
1869 uv_get_process_title(buffer, sizeof(buffer));
1870 return scope.Close(String::New(buffer));
Ryan Dahl5185c152010-06-18 07:26:491871}
1872
1873
1874static void ProcessTitleSetter(Local<String> property,
1875 Local<Value> value,
1876 const AccessorInfo& info) {
1877 HandleScope scope;
1878 String::Utf8Value title(value->ToString());
Igor Zinkovsky500c8f42011-12-15 20:36:051879 // TODO: protect with a lock
1880 uv_set_process_title(*title);
Ryan Dahl5185c152010-06-18 07:26:491881}
1882
1883
Ben Noordhuisb4def482010-10-15 13:48:341884static Handle<Value> EnvGetter(Local<String> property,
1885 const AccessorInfo& info) {
1886 String::Utf8Value key(property);
1887 const char* val = getenv(*key);
1888 if (val) {
1889 HandleScope scope;
1890 return scope.Close(String::New(val));
1891 }
1892 return Undefined();
1893}
1894
1895
1896static Handle<Value> EnvSetter(Local<String> property,
1897 Local<Value> value,
1898 const AccessorInfo& info) {
Ryan Dahle6b06bc2011-08-11 00:14:231899 HandleScope scope;
Ben Noordhuisb4def482010-10-15 13:48:341900 String::Utf8Value key(property);
1901 String::Utf8Value val(value);
Ryan Dahle6b06bc2011-08-11 00:14:231902
Bert Belder30bab522010-11-25 00:09:061903#ifdef __POSIX__
Ben Noordhuisb4def482010-10-15 13:48:341904 setenv(*key, *val, 1);
Bert Belder30bab522010-11-25 00:09:061905#else // __WIN32__
Ryan Dahle6b06bc2011-08-11 00:14:231906 int n = key.length() + val.length() + 2;
1907 char* pair = new char[n];
1908 snprintf(pair, n, "%s=%s", *key, *val);
1909 int r = _putenv(pair);
1910 if (r) {
1911 fprintf(stderr, "error putenv: '%s'\n", pair);
1912 }
1913 delete [] pair;
Bert Belder30bab522010-11-25 00:09:061914#endif
Ryan Dahle6b06bc2011-08-11 00:14:231915
Ben Noordhuisb4def482010-10-15 13:48:341916 return value;
1917}
1918
1919
1920static Handle<Integer> EnvQuery(Local<String> property,
1921 const AccessorInfo& info) {
1922 String::Utf8Value key(property);
1923 if (getenv(*key)) {
1924 HandleScope scope;
1925 return scope.Close(Integer::New(None));
1926 }
1927 return Handle<Integer>();
1928}
1929
1930
1931static Handle<Boolean> EnvDeleter(Local<String> property,
1932 const AccessorInfo& info) {
Ryan Dahle6b06bc2011-08-11 00:14:231933 HandleScope scope;
1934
Ben Noordhuisb4def482010-10-15 13:48:341935 String::Utf8Value key(property);
Ryan Dahle6b06bc2011-08-11 00:14:231936
Ben Noordhuisb4def482010-10-15 13:48:341937 if (getenv(*key)) {
Bert Belder30bab522010-11-25 00:09:061938#ifdef __POSIX__
Ben Noordhuisb4def482010-10-15 13:48:341939 unsetenv(*key); // prototyped as `void unsetenv(const char*)` on some platforms
Bert Belder30bab522010-11-25 00:09:061940#else
Ryan Dahle6b06bc2011-08-11 00:14:231941 int n = key.length() + 2;
1942 char* pair = new char[n];
1943 snprintf(pair, n, "%s=", *key);
1944 int r = _putenv(pair);
1945 if (r) {
1946 fprintf(stderr, "error unsetenv: '%s'\n", pair);
1947 }
1948 delete [] pair;
Bert Belder30bab522010-11-25 00:09:061949#endif
Ben Noordhuisb4def482010-10-15 13:48:341950 return True();
1951 }
Ryan Dahle6b06bc2011-08-11 00:14:231952
Ben Noordhuisb4def482010-10-15 13:48:341953 return False();
1954}
1955
1956
1957static Handle<Array> EnvEnumerator(const AccessorInfo& info) {
1958 HandleScope scope;
1959
1960 int size = 0;
1961 while (environ[size]) size++;
1962
1963 Local<Array> env = Array::New(size);
1964
1965 for (int i = 0; i < size; ++i) {
1966 const char* var = environ[i];
1967 const char* s = strchr(var, '=');
1968 const int length = s ? s - var : strlen(var);
1969 env->Set(i, String::New(var, length));
1970 }
1971
1972 return scope.Close(env);
1973}
1974
1975
Ben Noordhuisaa0308d2011-07-23 21:16:481976static Handle<Object> GetFeatures() {
1977 HandleScope scope;
1978
1979 Local<Object> obj = Object::New();
Ryan Dahl52a40e02011-08-24 21:16:351980 obj->Set(String::NewSymbol("debug"),
1981#if defined(DEBUG) && DEBUG
1982 True()
1983#else
1984 False()
1985#endif
1986 );
1987
Ryan Dahlc8dbaf52011-10-11 21:38:381988 obj->Set(String::NewSymbol("uv"), True());
Ben Noordhuisaa0308d2011-07-23 21:16:481989 obj->Set(String::NewSymbol("ipv6"), True()); // TODO ping libuv
Fedor Indutny9010f5f2011-07-28 15:52:041990 obj->Set(String::NewSymbol("tls_npn"), Boolean::New(use_npn));
1991 obj->Set(String::NewSymbol("tls_sni"), Boolean::New(use_sni));
Ben Noordhuisaa0308d2011-07-23 21:16:481992 obj->Set(String::NewSymbol("tls"),
1993 Boolean::New(get_builtin_module("crypto") != NULL));
1994
1995 return scope.Close(obj);
1996}
1997
1998
Bert Belder829735e2011-11-04 15:23:021999static Handle<Value> DebugProcess(const Arguments& args);
Fedor Indutnyb0388cc2011-12-10 16:52:072000static Handle<Value> DebugPause(const Arguments& args);
Bert Belder829735e2011-11-04 15:23:022001
Dean McNameef67e8f22011-03-15 22:39:162002Handle<Object> SetupProcessObject(int argc, char *argv[]) {
Ryan27b268b2009-06-17 13:05:442003 HandleScope scope;
2004
Ryan Dahlcd1ec272011-01-02 09:44:422005 int i, j;
2006
Ryan Dahlad0a4ce2009-10-29 22:34:102007 Local<FunctionTemplate> process_template = FunctionTemplate::New();
Ryan27b268b2009-06-17 13:05:442008
Ryan Dahlad0a4ce2009-10-29 22:34:102009 process = Persistent<Object>::New(process_template->GetFunction()->NewInstance());
2010
Ben Noordhuis74a82152012-02-03 15:32:002011
Ryan Dahl5185c152010-06-18 07:26:492012 process->SetAccessor(String::New("title"),
2013 ProcessTitleGetter,
2014 ProcessTitleSetter);
2015
Ryan Dahlf4811832009-11-02 23:21:002016 // process.version
Ryan Dahlad0a4ce2009-10-29 22:34:102017 process->Set(String::NewSymbol("version"), String::New(NODE_VERSION));
Ryan Dahl39b432e2010-08-17 18:24:102018
Ryan Dahla979ab92011-08-04 23:40:072019#ifdef NODE_PREFIX
Ryan Dahlf4811832009-11-02 23:21:002020 // process.installPrefix
Ryan Dahlad0a4ce2009-10-29 22:34:102021 process->Set(String::NewSymbol("installPrefix"), String::New(NODE_PREFIX));
Ryan Dahla979ab92011-08-04 23:40:072022#endif
Ryan1bf9be62009-08-03 15:51:352023
Ryan Dahlea9ee1f2011-07-28 02:30:322024 // process.moduleLoadList
2025 module_load_list = Persistent<Array>::New(Array::New());
2026 process->Set(String::NewSymbol("moduleLoadList"), module_load_list);
2027
Ryan Dahl39b432e2010-08-17 18:24:102028 Local<Object> versions = Object::New();
2029 char buf[20];
2030 process->Set(String::NewSymbol("versions"), versions);
2031 // +1 to get rid of the leading 'v'
2032 versions->Set(String::NewSymbol("node"), String::New(NODE_VERSION+1));
2033 versions->Set(String::NewSymbol("v8"), String::New(V8::GetVersion()));
2034 versions->Set(String::NewSymbol("ares"), String::New(ARES_VERSION_STR));
Bert Belder9cec08e2011-05-23 23:42:222035 snprintf(buf, 20, "%d.%d", UV_VERSION_MAJOR, UV_VERSION_MINOR);
2036 versions->Set(String::NewSymbol("uv"), String::New(buf));
Peter Bright13d6a1f2011-08-06 04:23:252037#if HAVE_OPENSSL
Ryan Dahlcd1ec272011-01-02 09:44:422038 // Stupid code to slice out the version string.
2039 int c, l = strlen(OPENSSL_VERSION_TEXT);
Ben Noordhuise0297ca2011-10-14 15:05:022040 for (i = j = 0; i < l; i++) {
Ryan Dahlcd1ec272011-01-02 09:44:422041 c = OPENSSL_VERSION_TEXT[i];
2042 if ('0' <= c && c <= '9') {
2043 for (j = i + 1; j < l; j++) {
2044 c = OPENSSL_VERSION_TEXT[j];
2045 if (c == ' ') break;
2046 }
2047 break;
2048 }
2049 }
2050 versions->Set(String::NewSymbol("openssl"),
2051 String::New(OPENSSL_VERSION_TEXT + i, j - i));
2052#endif
Ryan Dahl39b432e2010-08-17 18:24:102053
2054
2055
Nathan Rajlichb1be5402011-04-26 03:24:512056 // process.arch
2057 process->Set(String::NewSymbol("arch"), String::New(ARCH));
2058
Ryan Dahlf4811832009-11-02 23:21:002059 // process.platform
Ryan Dahl37704622011-01-06 03:05:592060 process->Set(String::NewSymbol("platform"), String::New(PLATFORM));
Ryan Dahlf4811832009-11-02 23:21:002061
Ryan Dahlf3ad6352010-02-03 20:19:082062 // process.argv
Jeremy Ashkenas2916a2a2010-02-21 06:41:272063 Local<Array> arguments = Array::New(argc - option_end_index + 1);
Ryan1910c112009-09-11 18:05:222064 arguments->Set(Integer::New(0), String::New(argv[0]));
Peter Griess78d33f42010-06-04 15:29:102065 for (j = 1, i = option_end_index; i < argc; j++, i++) {
Ryan27b268b2009-06-17 13:05:442066 Local<String> arg = String::New(argv[i]);
Ryan1910c112009-09-11 18:05:222067 arguments->Set(Integer::New(j), arg);
Ryan27b268b2009-06-17 13:05:442068 }
Ryan Dahl38814552009-10-09 15:15:472069 // assign it
Ryan Dahlf3ad6352010-02-03 20:19:082070 process->Set(String::NewSymbol("argv"), arguments);
Ryan27b268b2009-06-17 13:05:442071
Ryan Dahlf3ad6352010-02-03 20:19:082072 // create process.env
Ben Noordhuisb4def482010-10-15 13:48:342073 Local<ObjectTemplate> envTemplate = ObjectTemplate::New();
Ryan Dahlea9006a2010-12-02 23:59:352074 envTemplate->SetNamedPropertyHandler(EnvGetter,
2075 EnvSetter,
2076 EnvQuery,
2077 EnvDeleter,
2078 EnvEnumerator,
2079 Undefined());
Ben Noordhuisb4def482010-10-15 13:48:342080 Local<Object> env = envTemplate->NewInstance();
Ryan Dahlf3ad6352010-02-03 20:19:082081 process->Set(String::NewSymbol("env"), env);
2082
Brandon Beacher334d56d2009-10-14 21:56:122083 process->Set(String::NewSymbol("pid"), Integer::New(getpid()));
Ben Noordhuisaa0308d2011-07-23 21:16:482084 process->Set(String::NewSymbol("features"), GetFeatures());
Ryandc39e822009-09-10 12:07:352085
TJ Holowaychuk9481bc12010-10-07 02:05:012086 // -e, --eval
2087 if (eval_string) {
2088 process->Set(String::NewSymbol("_eval"), String::New(eval_string));
Ben Noordhuis3d22dbf2011-12-01 16:21:002089 process->Set(String::NewSymbol("_print_eval"), Boolean::New(print_eval));
TJ Holowaychuk9481bc12010-10-07 02:05:012090 }
2091
Marshall Culpepperca35ba62010-06-22 06:31:192092 size_t size = 2*PATH_MAX;
Peter Bright13d6a1f2011-08-06 04:23:252093 char* execPath = new char[size];
Ryan Dahl48f65b32011-07-15 17:46:112094 if (uv_exepath(execPath, &size) != 0) {
Marshall Culpepperca35ba62010-06-22 06:31:192095 // as a last ditch effort, fallback on argv[0] ?
2096 process->Set(String::NewSymbol("execPath"), String::New(argv[0]));
2097 } else {
Ryan Dahl00a1d612010-11-16 03:06:182098 process->Set(String::NewSymbol("execPath"), String::New(execPath, size));
Marshall Culpepperca35ba62010-06-22 06:31:192099 }
Peter Bright13d6a1f2011-08-06 04:23:252100 delete [] execPath;
Marshall Culpepperca35ba62010-06-22 06:31:192101
2102
Ryan Dahl38814552009-10-09 15:15:472103 // define various internal methods
Ryan Dahl4e7e2f82010-04-13 22:39:152104 NODE_SET_METHOD(process, "_needTickCallback", NeedTickCallback);
Ryan Dahlad0a4ce2009-10-29 22:34:102105 NODE_SET_METHOD(process, "reallyExit", Exit);
Robert Mustacchi22404862011-12-15 01:02:152106 NODE_SET_METHOD(process, "abort", Abort);
Brandon Beacher47fcf782009-11-03 18:13:382107 NODE_SET_METHOD(process, "chdir", Chdir);
Ryan Dahlad0a4ce2009-10-29 22:34:102108 NODE_SET_METHOD(process, "cwd", Cwd);
Bert Belder30bab522010-11-25 00:09:062109
Bert Belder86fba382011-11-24 01:38:342110#ifdef _WIN32
2111 NODE_SET_METHOD(process, "_cwdForDrive", CwdForDrive);
2112#endif
2113
Ryan Dahlacc120a2011-08-09 20:53:562114 NODE_SET_METHOD(process, "umask", Umask);
2115
Bert Belder30bab522010-11-25 00:09:062116#ifdef __POSIX__
Michael Cartera3860762010-02-08 06:13:102117 NODE_SET_METHOD(process, "getuid", GetUid);
2118 NODE_SET_METHOD(process, "setuid", SetUid);
James Duncandf1c1e52010-02-23 22:45:022119
2120 NODE_SET_METHOD(process, "setgid", SetGid);
2121 NODE_SET_METHOD(process, "getgid", GetGid);
Igor Zinkovsky24a69d22011-11-02 22:06:482122#endif // __POSIX__
James Duncandf1c1e52010-02-23 22:45:022123
Ryan Dahl6eca9482010-09-17 06:13:032124 NODE_SET_METHOD(process, "_kill", Kill);
Bert Belder30bab522010-11-25 00:09:062125
Bert Belder829735e2011-11-04 15:23:022126 NODE_SET_METHOD(process, "_debugProcess", DebugProcess);
Fedor Indutnyb0388cc2011-12-10 16:52:072127 NODE_SET_METHOD(process, "_debugPause", DebugPause);
Bert Belder829735e2011-11-04 15:23:022128
Bert Belderdd93c532011-10-28 10:05:092129 NODE_SET_METHOD(process, "dlopen", DLOpen);
2130
Tom Hughescf78ce52011-03-04 23:57:542131 NODE_SET_METHOD(process, "uptime", Uptime);
Ryan Dahlb3b3cfe2009-11-03 12:00:422132 NODE_SET_METHOD(process, "memoryUsage", MemoryUsage);
Ryan Dahlc344fbc2011-10-06 21:59:382133 NODE_SET_METHOD(process, "uvCounters", UVCounters);
Ryan27b268b2009-06-17 13:05:442134
Ryan Dahl627fb5a2010-03-15 20:48:032135 NODE_SET_METHOD(process, "binding", Binding);
2136
Dean McNameef67e8f22011-03-15 22:39:162137 return process;
2138}
2139
2140
2141static void AtExit() {
Ryan Dahl4e43afd2011-09-30 20:11:472142 uv_tty_reset_mode();
Dean McNameef67e8f22011-03-15 22:39:162143}
2144
2145
2146static void SignalExit(int signal) {
Ryan Dahl4e43afd2011-09-30 20:11:472147 uv_tty_reset_mode();
Dean McNameef67e8f22011-03-15 22:39:162148 _exit(1);
2149}
2150
2151
Ryan Dahl7547c7d2011-12-07 01:00:332152void Load(Handle<Object> process_l) {
Ryan Dahl9f5643f2010-01-31 07:22:342153 // Compile, execute the src/node.js file. (Which was included as static C
2154 // string in node_natives.h. 'natve_node' is the string containing that
2155 // source code.)
Ryan Dahlb20c3432010-02-12 05:55:082156
Ryan Dahl9f5643f2010-01-31 07:22:342157 // The node.js file returns a function 'f'
Ryan Dahlb20c3432010-02-12 05:55:082158
Dean McNameef67e8f22011-03-15 22:39:162159 atexit(AtExit);
2160
Ryan Dahl9f5643f2010-01-31 07:22:342161 TryCatch try_catch;
Ryan Dahl9f5643f2010-01-31 07:22:342162
Tom Hughes74954ce2011-03-08 06:00:512163 Local<Value> f_value = ExecuteString(MainSource(),
2164 IMMUTABLE_STRING("node.js"));
Ryan Dahl9f5643f2010-01-31 07:22:342165 if (try_catch.HasCaught()) {
Ryan Dahlab068db2010-05-09 20:54:582166 ReportException(try_catch, true);
Ryan Dahl9f5643f2010-01-31 07:22:342167 exit(10);
2168 }
Ryan Dahl9f5643f2010-01-31 07:22:342169 assert(f_value->IsFunction());
2170 Local<Function> f = Local<Function>::Cast(f_value);
2171
2172 // Now we call 'f' with the 'process' variable that we've built up with
2173 // all our bindings. Inside node.js we'll take care of assigning things to
2174 // their places.
Ryan Dahlb20c3432010-02-12 05:55:082175
Ryan Dahl9f5643f2010-01-31 07:22:342176 // We start the process this way in order to be more modular. Developers
2177 // who do not like how 'src/node.js' setups the module system but do like
2178 // Node's I/O bindings may want to replace 'f' with their own function.
2179
Ryan Dahlf8ce8482010-09-17 07:01:072180 // Add a reference to the global object
2181 Local<Object> global = v8::Context::GetCurrent()->Global();
Ryan Dahl7547c7d2011-12-07 01:00:332182 Local<Value> args[1] = { Local<Value>::New(process_l) };
Zoran Tomicicd98ea702010-02-22 05:15:442183
Ryan Dahle9257b82011-02-10 02:50:262184#ifdef HAVE_DTRACE
Ryan Dahl068b7332011-01-25 01:50:102185 InitDTrace(global);
Ryan Dahle9257b82011-02-10 02:50:262186#endif
Ryan Dahl068b7332011-01-25 01:50:102187
Ryan Dahlb20c3432010-02-12 05:55:082188 f->Call(global, 1, args);
Ryan Dahl9f5643f2010-01-31 07:22:342189
Ryan Dahl8a52fb72010-07-01 18:10:222190 if (try_catch.HasCaught()) {
2191 ReportException(try_catch, true);
2192 exit(11);
Ryan Dahl9f5643f2010-01-31 07:22:342193 }
Ryan27b268b2009-06-17 13:05:442194}
2195
Zoran Tomicicd98ea702010-02-22 05:15:442196static void PrintHelp();
2197
2198static void ParseDebugOpt(const char* arg) {
2199 const char *p = 0;
2200
2201 use_debug_agent = true;
2202 if (!strcmp (arg, "--debug-brk")) {
2203 debug_wait_connect = true;
2204 return;
2205 } else if (!strcmp(arg, "--debug")) {
2206 return;
2207 } else if (strstr(arg, "--debug-brk=") == arg) {
2208 debug_wait_connect = true;
2209 p = 1 + strchr(arg, '=');
2210 debug_port = atoi(p);
2211 } else if (strstr(arg, "--debug=") == arg) {
2212 p = 1 + strchr(arg, '=');
2213 debug_port = atoi(p);
2214 }
2215 if (p && debug_port > 1024 && debug_port < 65536)
2216 return;
2217
2218 fprintf(stderr, "Bad debug option.\n");
2219 if (p) fprintf(stderr, "Debug port must be in range 1025 to 65535.\n");
2220
2221 PrintHelp();
2222 exit(1);
2223}
2224
Ryand6c9d312009-09-11 14:02:292225static void PrintHelp() {
Steve Engledow292345f2011-07-05 11:07:082226 printf("Usage: node [options] [ -e script | script.js ] [arguments] \n"
Ryan Dahl87339a22011-10-12 09:56:292227 " node debug script.js [arguments] \n"
Ryan Dahl4fa712c2011-01-13 23:28:162228 "\n"
Ryan Dahl209b2192010-03-08 16:33:102229 "Options:\n"
Tom Hughes78da9cb2010-10-18 22:50:562230 " -v, --version print node's version\n"
Steve Engledow292345f2011-07-05 11:07:082231 " -e, --eval script evaluate script\n"
Ben Noordhuis3d22dbf2011-12-01 16:21:002232 " -p, --print print result of --eval\n"
Tom Hughes78da9cb2010-10-18 22:50:562233 " --v8-options print v8 command line options\n"
2234 " --vars print various compiled-in variables\n"
2235 " --max-stack-size=val set max v8 stack size (bytes)\n"
Ryan Dahl209b2192010-03-08 16:33:102236 "\n"
Ben Noordhuisfdf180f2011-12-05 07:42:112237 "Environment variables:\n"
2238#ifdef _WIN32
2239 "NODE_PATH ';'-separated list of directories\n"
2240#else
Tom Hughes78da9cb2010-10-18 22:50:562241 "NODE_PATH ':'-separated list of directories\n"
Ben Noordhuisfdf180f2011-12-05 07:42:112242#endif
isaacsc050d0f2011-07-25 01:04:452243 " prefixed to the module search path.\n"
Tom Hughes78da9cb2010-10-18 22:50:562244 "NODE_MODULE_CONTEXTS Set to 1 to load modules in their own\n"
2245 " global contexts.\n"
Ryan Dahl4fa712c2011-01-13 23:28:162246 "NODE_DISABLE_COLORS Set to 1 to disable colors in the REPL\n"
Ryan Dahl209b2192010-03-08 16:33:102247 "\n"
Ryan Dahl4fa712c2011-01-13 23:28:162248 "Documentation can be found at http://nodejs.org/\n");
Ryan11df2522009-08-03 16:19:402249}
2250
Ryan Dahl38814552009-10-09 15:15:472251// Parse node command line arguments.
Dean McNameef67e8f22011-03-15 22:39:162252static void ParseArgs(int argc, char **argv) {
Peter Griess78d33f42010-06-04 15:29:102253 int i;
2254
Ryan Dahle742d072009-10-09 11:25:042255 // TODO use parse opts
Dean McNameef67e8f22011-03-15 22:39:162256 for (i = 1; i < argc; i++) {
Ryan11df2522009-08-03 16:19:402257 const char *arg = argv[i];
Zoran Tomicicd98ea702010-02-22 05:15:442258 if (strstr(arg, "--debug") == arg) {
2259 ParseDebugOpt(arg);
Jonas Pfenniger8f59ccc2010-02-24 21:11:082260 argv[i] = const_cast<char*>("");
Ryan1910c112009-09-11 18:05:222261 } else if (strcmp(arg, "--version") == 0 || strcmp(arg, "-v") == 0) {
Ryan11df2522009-08-03 16:19:402262 printf("%s\n", NODE_VERSION);
2263 exit(0);
Ryan Dahl40e42e82010-03-08 17:10:242264 } else if (strcmp(arg, "--vars") == 0) {
Ryan Dahla979ab92011-08-04 23:40:072265#ifdef NODE_PREFIX
Ryan Dahl40e42e82010-03-08 17:10:242266 printf("NODE_PREFIX: %s\n", NODE_PREFIX);
Ryan Dahla979ab92011-08-04 23:40:072267#endif
2268#ifdef NODE_CFLAGS
Ryan Dahl40e42e82010-03-08 17:10:242269 printf("NODE_CFLAGS: %s\n", NODE_CFLAGS);
Ryan Dahla979ab92011-08-04 23:40:072270#endif
Ryaned9c3362009-09-01 13:28:102271 exit(0);
Tom Hughes78da9cb2010-10-18 22:50:562272 } else if (strstr(arg, "--max-stack-size=") == arg) {
2273 const char *p = 0;
2274 p = 1 + strchr(arg, '=');
2275 max_stack_size = atoi(p);
2276 argv[i] = const_cast<char*>("");
Ryan11df2522009-08-03 16:19:402277 } else if (strcmp(arg, "--help") == 0 || strcmp(arg, "-h") == 0) {
2278 PrintHelp();
2279 exit(0);
Ben Noordhuis3d22dbf2011-12-01 16:21:002280 } else if (strcmp(arg, "--eval") == 0 || strcmp(arg, "-e") == 0 ||
2281 strcmp(arg, "-pe") == 0) {
Dean McNameef67e8f22011-03-15 22:39:162282 if (argc <= i + 1) {
TJ Holowaychuk9481bc12010-10-07 02:05:012283 fprintf(stderr, "Error: --eval requires an argument\n");
2284 exit(1);
2285 }
Ben Noordhuis3d22dbf2011-12-01 16:21:002286 if (arg[1] == 'p') {
2287 print_eval = true;
2288 }
TJ Holowaychuk9481bc12010-10-07 02:05:012289 argv[i] = const_cast<char*>("");
2290 eval_string = argv[++i];
Ben Noordhuis3d22dbf2011-12-01 16:21:002291 } else if (strcmp(arg, "--print") == 0 || strcmp(arg, "-p") == 0) {
2292 print_eval = true;
2293 argv[i] = const_cast<char*>("");
Ryan11df2522009-08-03 16:19:402294 } else if (strcmp(arg, "--v8-options") == 0) {
Jonas Pfenniger8f59ccc2010-02-24 21:11:082295 argv[i] = const_cast<char*>("--help");
Jeremy Ashkenas2916a2a2010-02-21 06:41:272296 } else if (argv[i][0] != '-') {
Jeremy Ashkenas2916a2a2010-02-21 06:41:272297 break;
Ryan11df2522009-08-03 16:19:402298 }
2299 }
Peter Griess78d33f42010-06-04 15:29:102300
2301 option_end_index = i;
Ryan11df2522009-08-03 16:19:402302}
2303
Bert Belder829735e2011-11-04 15:23:022304
Ben Noordhuis74a82152012-02-03 15:32:002305static Isolate* node_isolate = NULL;
2306static volatile bool debugger_running = false;
2307
Ryan Dahl2a7e7b12010-12-18 19:17:292308static void EnableDebug(bool wait_connect) {
Bert Belder829735e2011-11-04 15:23:022309 // If we're called from another thread, make sure to enter the right
2310 // v8 isolate.
2311 node_isolate->Enter();
2312
Ryan Dahl2a7e7b12010-12-18 19:17:292313 // Start the debug thread and it's associated TCP server on port 5858.
Fedor Indutnyb0388cc2011-12-10 16:52:072314 bool r = v8::Debug::EnableAgent("node " NODE_VERSION, debug_port);
Ryan Dahl2a7e7b12010-12-18 19:17:292315
2316 if (wait_connect) {
2317 // Set up an empty handler so v8 will not continue until a debugger
2318 // attaches. This is the same behavior as Debug::EnableAgent(_,_,true)
2319 // except we don't break at the beginning of the script.
2320 // see Debugger::StartAgent in debug.cc of v8/src
Fedor Indutnyb0388cc2011-12-10 16:52:072321 v8::Debug::SetMessageHandler2(node::DebugBreakMessageHandler);
Ryan Dahl2a7e7b12010-12-18 19:17:292322 }
2323
2324 // Crappy check that everything went well. FIXME
2325 assert(r);
2326
2327 // Print out some information.
Fedor Indutny26aab0d2011-09-24 07:28:272328 fprintf(stderr, "debugger listening on port %d\n", debug_port);
Bert Belder829735e2011-11-04 15:23:022329 fflush(stderr);
Fedor Indutny9e09fc02011-09-24 05:44:082330
2331 debugger_running = true;
Bert Belder829735e2011-11-04 15:23:022332
2333 node_isolate->Exit();
Ryan Dahl2a7e7b12010-12-18 19:17:292334}
2335
2336
Fedor Indutny82d0ac72011-09-24 13:51:592337#ifdef __POSIX__
Fedor Indutny26aab0d2011-09-24 07:28:272338static void EnableDebugSignalHandler(int signal) {
2339 // Break once process will return execution to v8
Bert Belder829735e2011-11-04 15:23:022340 v8::Debug::DebugBreak(node_isolate);
Ryan Dahl4ab54762011-03-01 17:59:172341
Fedor Indutny26aab0d2011-09-24 07:28:272342 if (!debugger_running) {
Ryan Dahl4ab54762011-03-01 17:59:172343 fprintf(stderr, "Hit SIGUSR1 - starting debugger agent.\n");
2344 EnableDebug(false);
2345 }
Ryan Dahl2a7e7b12010-12-18 19:17:292346}
2347
2348
Bert Belder829735e2011-11-04 15:23:022349static void RegisterSignalHandler(int signal, void (*handler)(int)) {
Tom Hughesf61b1102010-10-12 21:01:582350 struct sigaction sa;
2351
2352 memset(&sa, 0, sizeof(sa));
2353 sa.sa_handler = handler;
2354 sigfillset(&sa.sa_mask);
Bert Belder829735e2011-11-04 15:23:022355 sigaction(signal, &sa, NULL);
2356}
2357
2358
2359Handle<Value> DebugProcess(const Arguments& args) {
2360 HandleScope scope;
2361
2362 if (args.Length() != 1) {
2363 return ThrowException(Exception::Error(
2364 String::New("Invalid number of arguments.")));
2365 }
2366
2367 pid_t pid;
2368 int r;
2369
2370 pid = args[0]->IntegerValue();
2371 r = kill(pid, SIGUSR1);
2372 if (r != 0) {
2373 return ThrowException(ErrnoException(errno, "kill"));
2374 }
2375
2376 return Undefined();
Tom Hughesf61b1102010-10-12 21:01:582377}
Bert Belder30bab522010-11-25 00:09:062378#endif // __POSIX__
Tom Hughesf61b1102010-10-12 21:01:582379
2380
Bert Belder829735e2011-11-04 15:23:022381#ifdef _WIN32
2382DWORD WINAPI EnableDebugThreadProc(void* arg) {
2383 // Break once process will return execution to v8
2384 if (!debugger_running) {
2385 for (int i = 0; i < 1; i++) {
2386 fprintf(stderr, "Starting debugger agent.\r\n");
2387 fflush(stderr);
2388 EnableDebug(false);
2389 }
2390 }
2391
2392 v8::Debug::DebugBreak();
2393
2394 return 0;
2395}
2396
2397
2398static int GetDebugSignalHandlerMappingName(DWORD pid, char* buf, size_t buf_len) {
2399 return snprintf(buf, buf_len, "node-debug-handler-%u", pid);
2400}
2401
2402
2403static int RegisterDebugSignalHandler() {
2404 char mapping_name[32];
2405 HANDLE mapping_handle;
2406 DWORD pid;
2407 LPTHREAD_START_ROUTINE* handler;
2408
2409 pid = GetCurrentProcessId();
2410
2411 if (GetDebugSignalHandlerMappingName(pid,
2412 mapping_name,
2413 sizeof mapping_name) < 0) {
2414 return -1;
2415 }
2416
2417 mapping_handle = CreateFileMappingA(INVALID_HANDLE_VALUE,
2418 NULL,
2419 PAGE_READWRITE,
2420 0,
2421 sizeof *handler,
2422 mapping_name);
2423 if (mapping_handle == NULL) {
2424 return -1;
2425 }
2426
2427 handler = (LPTHREAD_START_ROUTINE*) MapViewOfFile(mapping_handle,
2428 FILE_MAP_ALL_ACCESS,
2429 0,
2430 0,
2431 sizeof *handler);
2432 if (handler == NULL) {
2433 CloseHandle(mapping_handle);
2434 return -1;
2435 }
2436
2437 *handler = EnableDebugThreadProc;
2438
2439 UnmapViewOfFile((void*) handler);
2440
2441 return 0;
2442}
2443
2444
2445static Handle<Value> DebugProcess(const Arguments& args) {
2446 HandleScope scope;
2447 Handle<Value> rv = Undefined();
2448 DWORD pid;
Ryan Dahl7547c7d2011-12-07 01:00:332449 HANDLE process_l = NULL;
Bert Belder829735e2011-11-04 15:23:022450 HANDLE thread = NULL;
2451 HANDLE mapping = NULL;
2452 char mapping_name[32];
2453 LPTHREAD_START_ROUTINE* handler = NULL;
2454
2455 if (args.Length() != 1) {
2456 rv = ThrowException(Exception::Error(String::New("Invalid number of arguments.")));
2457 goto out;
2458 }
2459
2460 pid = (DWORD) args[0]->IntegerValue();
2461
Ryan Dahl7547c7d2011-12-07 01:00:332462 process_l = OpenProcess(PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION |
Bert Belder829735e2011-11-04 15:23:022463 PROCESS_VM_OPERATION | PROCESS_VM_WRITE |
2464 PROCESS_VM_READ,
2465 FALSE,
2466 pid);
Ryan Dahl7547c7d2011-12-07 01:00:332467 if (process_l == NULL) {
Bert Belder829735e2011-11-04 15:23:022468 rv = ThrowException(WinapiErrnoException(GetLastError(), "OpenProcess"));
2469 goto out;
2470 }
2471
2472 if (GetDebugSignalHandlerMappingName(pid,
2473 mapping_name,
2474 sizeof mapping_name) < 0) {
2475 rv = ThrowException(ErrnoException(errno, "sprintf"));
2476 goto out;
2477 }
2478
2479 mapping = OpenFileMapping(FILE_MAP_READ, FALSE, mapping_name);
2480 if (mapping == NULL) {
2481 rv = ThrowException(WinapiErrnoException(GetLastError(), "sprintf"));
2482 goto out;
2483 }
2484
2485 handler = (LPTHREAD_START_ROUTINE*) MapViewOfFile(mapping,
2486 FILE_MAP_READ,
2487 0,
2488 0,
2489 sizeof *handler);
2490 if (handler == NULL || *handler == NULL) {
2491 rv = ThrowException(WinapiErrnoException(GetLastError(), "MapViewOfFile"));
2492 goto out;
2493 }
2494
Ryan Dahl7547c7d2011-12-07 01:00:332495 thread = CreateRemoteThread(process_l,
Bert Belder829735e2011-11-04 15:23:022496 NULL,
2497 0,
2498 *handler,
2499 NULL,
2500 0,
2501 NULL);
2502 if (thread == NULL) {
2503 rv = ThrowException(WinapiErrnoException(GetLastError(),
2504 "CreateRemoteThread"));
2505 goto out;
2506 }
2507
2508 // Wait for the thread to terminate
2509 if (WaitForSingleObject(thread, INFINITE) != WAIT_OBJECT_0) {
2510 rv = ThrowException(WinapiErrnoException(GetLastError(),
2511 "WaitForSingleObject"));
2512 goto out;
2513 }
2514
2515 out:
Ryan Dahl7547c7d2011-12-07 01:00:332516 if (process_l != NULL) {
2517 CloseHandle(process_l);
Bert Belder829735e2011-11-04 15:23:022518 }
2519 if (thread != NULL) {
2520 CloseHandle(thread);
2521 }
2522 if (handler != NULL) {
2523 UnmapViewOfFile(handler);
2524 }
2525 if (mapping != NULL) {
2526 CloseHandle(mapping);
2527 }
2528
2529 return Undefined();
2530}
2531#endif // _WIN32
2532
2533
Fedor Indutnyb0388cc2011-12-10 16:52:072534static Handle<Value> DebugPause(const Arguments& args) {
2535 v8::Debug::DebugBreak(node_isolate);
Ben Noordhuisaac717d2011-12-19 23:30:412536 return Undefined();
Fedor Indutnyb0388cc2011-12-10 16:52:072537}
2538
2539
Ben Noordhuis74a82152012-02-03 15:32:002540char** Init(int argc, char *argv[]) {
2541 // Initialize prog_start_time to get relative uptime.
2542 uv_uptime(&prog_start_time);
2543
Ryan Dahl5185c152010-06-18 07:26:492544 // Hack aroung with the argv pointer. Used for process.title = "blah".
Igor Zinkovsky500c8f42011-12-15 20:36:052545 argv = uv_setup_args(argc, argv);
Ryan Dahl5185c152010-06-18 07:26:492546
Ryan Dahl38814552009-10-09 15:15:472547 // Parse a few arguments which are specific to Node.
Dean McNameef67e8f22011-03-15 22:39:162548 node::ParseArgs(argc, argv);
Jeremy Ashkenas2916a2a2010-02-21 06:41:272549 // Parse the rest of the args (up to the 'option_end_index' (where '--' was
Ryan Dahl38814552009-10-09 15:15:472550 // in the command line))
Ryan Dahl7547c7d2011-12-07 01:00:332551 int v8argc = option_end_index;
Danny Coatesdc8c0792010-08-01 22:46:482552 char **v8argv = argv;
2553
Ryan Dahl7547c7d2011-12-07 01:00:332554 if (debug_wait_connect) {
Ryan Dahladec5442010-08-04 17:38:192555 // v8argv is a copy of argv up to the script file argument +2 if --debug-brk
Ryan Dahld408de82010-08-06 19:31:412556 // to expose the v8 debugger js object so that node.js can set
Ryan Dahladec5442010-08-04 17:38:192557 // a breakpoint on the first line of the startup script
2558 v8argc += 2;
2559 v8argv = new char*[v8argc];
Ryan Dahl7547c7d2011-12-07 01:00:332560 memcpy(v8argv, argv, sizeof(argv) * option_end_index);
2561 v8argv[option_end_index] = const_cast<char*>("--expose_debug_as");
2562 v8argv[option_end_index + 1] = const_cast<char*>("v8debug");
Ryan Dahladec5442010-08-04 17:38:192563 }
Tom Hughes78da9cb2010-10-18 22:50:562564
2565 // For the normal stack which moves from high to low addresses when frames
2566 // are pushed, we can compute the limit as stack_size bytes below the
2567 // the address of a stack variable (e.g. &stack_var) as an approximation
2568 // of the start of the stack (we're assuming that we haven't pushed a lot
2569 // of frames yet).
Ryan Dahl7547c7d2011-12-07 01:00:332570 if (max_stack_size != 0) {
Tom Hughes78da9cb2010-10-18 22:50:562571 uint32_t stack_var;
2572 ResourceConstraints constraints;
2573
Ryan Dahl7547c7d2011-12-07 01:00:332574 uint32_t *stack_limit = &stack_var - (max_stack_size / sizeof(uint32_t));
Tom Hughes78da9cb2010-10-18 22:50:562575 constraints.set_stack_limit(stack_limit);
2576 SetResourceConstraints(&constraints); // Must be done before V8::Initialize
2577 }
Danny Coatesdc8c0792010-08-01 22:46:482578 V8::SetFlagsFromCommandLine(&v8argc, v8argv, false);
Ryan23376302009-09-10 10:34:292579
Bert Belder30bab522010-11-25 00:09:062580#ifdef __POSIX__
Ryan Dahlb6c5cf62010-05-04 17:41:562581 // Ignore SIGPIPE
Tom Hughesf61b1102010-10-12 21:01:582582 RegisterSignalHandler(SIGPIPE, SIG_IGN);
2583 RegisterSignalHandler(SIGINT, SignalExit);
2584 RegisterSignalHandler(SIGTERM, SignalExit);
Bert Belder30bab522010-11-25 00:09:062585#endif // __POSIX__
Ryan Dahlb6c5cf62010-05-04 17:41:562586
Ben Noordhuis74a82152012-02-03 15:32:002587 uv_prepare_init(uv_default_loop(), &prepare_tick_watcher);
2588 uv_prepare_start(&prepare_tick_watcher, PrepareTick);
2589 uv_unref(uv_default_loop());
2590
2591 uv_check_init(uv_default_loop(), &check_tick_watcher);
2592 uv_check_start(&check_tick_watcher, node::CheckTick);
2593 uv_unref(uv_default_loop());
2594
2595 uv_idle_init(uv_default_loop(), &tick_spinner);
2596 uv_unref(uv_default_loop());
2597
2598 uv_check_init(uv_default_loop(), &gc_check);
2599 uv_check_start(&gc_check, node::Check);
2600 uv_unref(uv_default_loop());
2601
2602 uv_idle_init(uv_default_loop(), &gc_idle);
2603 uv_unref(uv_default_loop());
2604
2605 uv_timer_init(uv_default_loop(), &gc_timer);
2606 uv_unref(uv_default_loop());
2607
2608 V8::SetFatalErrorHandler(node::OnFatalError);
2609
2610 // Fetch a reference to the main isolate, so we have a reference to it
2611 // even when we need it to access it from another (debugger) thread.
2612 node_isolate = Isolate::GetCurrent();
2613
2614 // If the --debug flag was specified then initialize the debug thread.
2615 if (use_debug_agent) {
2616 EnableDebug(debug_wait_connect);
2617 } else {
2618#ifdef _WIN32
2619 RegisterDebugSignalHandler();
2620#else // Posix
2621 RegisterSignalHandler(SIGUSR1, EnableDebugSignalHandler);
2622#endif // __POSIX__
2623 }
2624
Ben Noordhuis5866f1a2011-12-09 18:02:332625 return argv;
2626}
Ben Noordhuis356992f2011-11-22 16:10:092627
Ben Noordhuis5866f1a2011-12-09 18:02:332628
2629void EmitExit(v8::Handle<v8::Object> process_l) {
2630 // process.emit('exit')
2631 Local<Value> emit_v = process_l->Get(String::New("emit"));
2632 assert(emit_v->IsFunction());
2633 Local<Function> emit = Local<Function>::Cast(emit_v);
2634 Local<Value> args[] = { String::New("exit") };
2635 TryCatch try_catch;
2636 emit->Call(process_l, 1, args);
2637 if (try_catch.HasCaught()) {
2638 FatalException(try_catch);
2639 }
2640}
2641
2642
Ben Noordhuis74a82152012-02-03 15:32:002643int Start(int argc, char *argv[]) {
2644 // This needs to run *before* V8::Initialize()
2645 argv = Init(argc, argv);
Ben Noordhuis5866f1a2011-12-09 18:02:332646
Ben Noordhuis74a82152012-02-03 15:32:002647 v8::V8::Initialize();
2648 v8::HandleScope handle_scope;
Ben Noordhuis809fdf22011-12-09 20:49:102649
Ben Noordhuis74a82152012-02-03 15:32:002650 // Create the one and only Context.
2651 Persistent<v8::Context> context = v8::Context::New();
2652 v8::Context::Scope context_scope(context);
Ryan Dahle742d072009-10-09 11:25:042653
Ryan Dahl7547c7d2011-12-07 01:00:332654 Handle<Object> process_l = SetupProcessObject(argc, argv);
Ben Noordhuis74a82152012-02-03 15:32:002655 v8_typed_array::AttachBindings(context->Global());
Ryan Dahl4d02e772011-12-17 07:23:342656
Ryan Dahl38814552009-10-09 15:15:472657 // Create all the objects, load modules, do everything.
2658 // so your next reading stop should be node::Load()!
Ryan Dahl7547c7d2011-12-07 01:00:332659 Load(process_l);
Ryan19478ed2009-03-03 00:56:152660
Ryan Dahld0beac72010-12-17 02:40:232661 // All our arguments are loaded. We've evaluated all of the scripts. We
2662 // might even have created TCP servers. Now we enter the main eventloop. If
2663 // there are no watchers on the loop (except for the ones that were
Bert Belder9cec08e2011-05-23 23:42:222664 // uv_unref'd) then this function exits. As long as there are active
Ryan Dahld0beac72010-12-17 02:40:232665 // watchers, it blocks.
Ben Noordhuis74a82152012-02-03 15:32:002666 uv_run(uv_default_loop());
Ryan Dahlc7b24ef2010-11-12 00:33:212667
Ryan Dahl7547c7d2011-12-07 01:00:332668 EmitExit(process_l);
Ben Noordhuis66116922011-11-23 19:50:282669
Ryan Dahl38814552009-10-09 15:15:472670#ifndef NDEBUG
Ryan Dahl38814552009-10-09 15:15:472671 // Clean up.
Ben Noordhuis74a82152012-02-03 15:32:002672 context.Dispose();
Ryan27b268b2009-06-17 13:05:442673 V8::Dispose();
Ryan Dahl38814552009-10-09 15:15:472674#endif // NDEBUG
Igor Zinkovskya58b6432011-07-07 20:54:302675
Ryanf6a7fe22009-06-08 14:17:332676 return 0;
Ryan19478ed2009-03-03 00:56:152677}
Ryan Dahl124fbed2010-09-19 20:13:572678
2679
2680} // namespace node