Merge branch 'v0.4'
[platform/upstream/nodejs.git] / src / node.cc
1 // 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.
21
22 #include <node.h>
23
24 #include <v8-debug.h>
25 #include <node_dtrace.h>
26
27 #include <locale.h>
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <strings.h>
31 #include <string.h>
32 #include <limits.h> /* PATH_MAX */
33 #include <assert.h>
34 #include <unistd.h>
35 #include <errno.h>
36 #include <sys/types.h>
37 #include <unistd.h> /* setuid, getuid */
38
39 #ifdef __MINGW32__
40 # include <platform_win32.h> /* winapi_perror() */
41 # include <platform_win32_winsock.h> /* wsa_init() */
42 #endif
43
44 #ifdef __POSIX__
45 # include <dlfcn.h> /* dlopen(), dlsym() */
46 # include <pwd.h> /* getpwnam() */
47 # include <grp.h> /* getgrnam() */
48 #endif
49
50 #include <platform.h>
51 #include <node_buffer.h>
52 #include <node_io_watcher.h>
53 #include <node_net.h>
54 #include <node_events.h>
55 #include <node_cares.h>
56 #include <node_file.h>
57 #if 0
58 // not in use
59 # include <node_idle_watcher.h>
60 #endif
61 #include <node_http_parser.h>
62 #include <node_signal_watcher.h>
63 #include <node_stat_watcher.h>
64 #include <node_timer.h>
65 #include <node_child_process.h>
66 #include <node_constants.h>
67 #include <node_stdio.h>
68 #include <node_javascript.h>
69 #include <node_version.h>
70 #include <node_string.h>
71 #ifdef HAVE_OPENSSL
72 # include <node_crypto.h>
73 #endif
74 #include <node_script.h>
75
76 #define ARRAY_SIZE(a) (sizeof(a) / sizeof(*(a)))
77
78 using namespace v8;
79
80 # ifdef __APPLE__
81 # include <crt_externs.h>
82 # define environ (*_NSGetEnviron())
83 # else
84 extern char **environ;
85 # endif
86
87 namespace node {
88
89 static Persistent<Object> process;
90
91 static Persistent<String> errno_symbol;
92 static Persistent<String> syscall_symbol;
93 static Persistent<String> errpath_symbol;
94 static Persistent<String> code_symbol;
95
96 static Persistent<String> rss_symbol;
97 static Persistent<String> vsize_symbol;
98 static Persistent<String> heap_total_symbol;
99 static Persistent<String> heap_used_symbol;
100
101 static Persistent<String> listeners_symbol;
102 static Persistent<String> uncaught_exception_symbol;
103 static Persistent<String> emit_symbol;
104
105
106 static char *eval_string = NULL;
107 static int option_end_index = 0;
108 static bool use_debug_agent = false;
109 static bool debug_wait_connect = false;
110 static int debug_port=5858;
111 static int max_stack_size = 0;
112
113 static ev_check check_tick_watcher;
114 static ev_prepare prepare_tick_watcher;
115 static ev_idle tick_spinner;
116 static bool need_tick_cb;
117 static Persistent<String> tick_callback_sym;
118
119 static ev_async eio_want_poll_notifier;
120 static ev_async eio_done_poll_notifier;
121 static ev_idle  eio_poller;
122
123 // Buffer for getpwnam_r(), getgrpam_r() and other misc callers; keep this
124 // scoped at file-level rather than method-level to avoid excess stack usage.
125 static char getbuf[PATH_MAX + 1];
126
127 // We need to notify V8 when we're idle so that it can run the garbage
128 // collector. The interface to this is V8::IdleNotification(). It returns
129 // true if the heap hasn't be fully compacted, and needs to be run again.
130 // Returning false means that it doesn't have anymore work to do.
131 //
132 // A rather convoluted algorithm has been devised to determine when Node is
133 // idle. You'll have to figure it out for yourself.
134 static ev_check gc_check;
135 static ev_idle  gc_idle;
136 static ev_timer gc_timer;
137 bool need_gc;
138
139
140 #define FAST_TICK 0.7
141 #define GC_WAIT_TIME 5.
142 #define RPM_SAMPLES 100
143 #define TICK_TIME(n) tick_times[(tick_time_head - (n)) % RPM_SAMPLES]
144 static ev_tstamp tick_times[RPM_SAMPLES];
145 static int tick_time_head;
146
147 static void StartGCTimer () {
148   if (!ev_is_active(&gc_timer)) {
149     ev_timer_start(EV_DEFAULT_UC_ &gc_timer);
150     ev_unref(EV_DEFAULT_UC);
151   }
152 }
153
154 static void StopGCTimer () {
155   if (ev_is_active(&gc_timer)) {
156     ev_ref(EV_DEFAULT_UC);
157     ev_timer_stop(EV_DEFAULT_UC_ &gc_timer);
158   }
159 }
160
161 static void Idle(EV_P_ ev_idle *watcher, int revents) {
162   assert(watcher == &gc_idle);
163   assert(revents == EV_IDLE);
164
165   //fprintf(stderr, "idle\n");
166
167   if (V8::IdleNotification()) {
168     ev_idle_stop(EV_A_ watcher);
169     StopGCTimer();
170   }
171 }
172
173
174 // Called directly after every call to select() (or epoll, or whatever)
175 static void Check(EV_P_ ev_check *watcher, int revents) {
176   assert(watcher == &gc_check);
177   assert(revents == EV_CHECK);
178
179   tick_times[tick_time_head] = ev_now(EV_DEFAULT_UC);
180   tick_time_head = (tick_time_head + 1) % RPM_SAMPLES;
181
182   StartGCTimer();
183
184   for (int i = 0; i < (int)(GC_WAIT_TIME/FAST_TICK); i++) {
185     double d = TICK_TIME(i+1) - TICK_TIME(i+2);
186     //printf("d = %f\n", d);
187     // If in the last 5 ticks the difference between
188     // ticks was less than 0.7 seconds, then continue.
189     if (d < FAST_TICK) {
190       //printf("---\n");
191       return;
192     }
193   }
194
195   // Otherwise start the gc!
196
197   //fprintf(stderr, "start idle 2\n");
198   ev_idle_start(EV_A_ &gc_idle);
199 }
200
201
202 static Handle<Value> NeedTickCallback(const Arguments& args) {
203   HandleScope scope;
204   need_tick_cb = true;
205   // TODO: this tick_spinner shouldn't be necessary. An ev_prepare should be
206   // sufficent, the problem is only in the case of the very last "tick" -
207   // there is nothing left to do in the event loop and libev will exit. The
208   // ev_prepare callback isn't called before exiting. Thus we start this
209   // tick_spinner to keep the event loop alive long enough to handle it.
210   ev_idle_start(EV_DEFAULT_UC_ &tick_spinner);
211   return Undefined();
212 }
213
214
215 static void Spin(EV_P_ ev_idle *watcher, int revents) {
216   assert(watcher == &tick_spinner);
217   assert(revents == EV_IDLE);
218 }
219
220
221 static void Tick(void) {
222   // Avoid entering a V8 scope.
223   if (!need_tick_cb) return;
224
225   need_tick_cb = false;
226   ev_idle_stop(EV_DEFAULT_UC_ &tick_spinner);
227
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
250 static void PrepareTick(EV_P_ ev_prepare *watcher, int revents) {
251   assert(watcher == &prepare_tick_watcher);
252   assert(revents == EV_PREPARE);
253   Tick();
254 }
255
256
257 static void CheckTick(EV_P_ ev_check *watcher, int revents) {
258   assert(watcher == &check_tick_watcher);
259   assert(revents == EV_CHECK);
260   Tick();
261 }
262
263
264 static void DoPoll(EV_P_ ev_idle *watcher, int revents) {
265   assert(watcher == &eio_poller);
266   assert(revents == EV_IDLE);
267
268   //printf("eio_poller\n");
269
270   if (eio_poll() != -1) {
271     //printf("eio_poller stop\n");
272     ev_idle_stop(EV_DEFAULT_UC_ watcher);
273   }
274 }
275
276
277 // Called from the main thread.
278 static void WantPollNotifier(EV_P_ ev_async *watcher, int revents) {
279   assert(watcher == &eio_want_poll_notifier);
280   assert(revents == EV_ASYNC);
281
282   //printf("want poll notifier\n");
283
284   if (eio_poll() == -1) {
285     //printf("eio_poller start\n");
286     ev_idle_start(EV_DEFAULT_UC_ &eio_poller);
287   }
288 }
289
290
291 static void DonePollNotifier(EV_P_ ev_async *watcher, int revents) {
292   assert(watcher == &eio_done_poll_notifier);
293   assert(revents == EV_ASYNC);
294
295   //printf("done poll notifier\n");
296
297   if (eio_poll() != -1) {
298     //printf("eio_poller stop\n");
299     ev_idle_stop(EV_DEFAULT_UC_ &eio_poller);
300   }
301 }
302
303
304 // EIOWantPoll() is called from the EIO thread pool each time an EIO
305 // request (that is, one of the node.fs.* functions) has completed.
306 static void EIOWantPoll(void) {
307   // Signal the main thread that eio_poll need to be processed.
308   ev_async_send(EV_DEFAULT_UC_ &eio_want_poll_notifier);
309 }
310
311
312 static void EIODonePoll(void) {
313   // Signal the main thread that we should stop calling eio_poll().
314   // from the idle watcher.
315   ev_async_send(EV_DEFAULT_UC_ &eio_done_poll_notifier);
316 }
317
318
319 static inline const char *errno_string(int errorno) {
320 #define ERRNO_CASE(e)  case e: return #e;
321   switch (errorno) {
322
323 #ifdef EACCES
324   ERRNO_CASE(EACCES);
325 #endif
326
327 #ifdef EADDRINUSE
328   ERRNO_CASE(EADDRINUSE);
329 #endif
330
331 #ifdef EADDRNOTAVAIL
332   ERRNO_CASE(EADDRNOTAVAIL);
333 #endif
334
335 #ifdef EAFNOSUPPORT
336   ERRNO_CASE(EAFNOSUPPORT);
337 #endif
338
339 #ifdef EAGAIN
340   ERRNO_CASE(EAGAIN);
341 #endif
342
343 #ifdef EWOULDBLOCK
344 # if EAGAIN != EWOULDBLOCK
345   ERRNO_CASE(EWOULDBLOCK);
346 # endif
347 #endif
348
349 #ifdef EALREADY
350   ERRNO_CASE(EALREADY);
351 #endif
352
353 #ifdef EBADF
354   ERRNO_CASE(EBADF);
355 #endif
356
357 #ifdef EBADMSG
358   ERRNO_CASE(EBADMSG);
359 #endif
360
361 #ifdef EBUSY
362   ERRNO_CASE(EBUSY);
363 #endif
364
365 #ifdef ECANCELED
366   ERRNO_CASE(ECANCELED);
367 #endif
368
369 #ifdef ECHILD
370   ERRNO_CASE(ECHILD);
371 #endif
372
373 #ifdef ECONNABORTED
374   ERRNO_CASE(ECONNABORTED);
375 #endif
376
377 #ifdef ECONNREFUSED
378   ERRNO_CASE(ECONNREFUSED);
379 #endif
380
381 #ifdef ECONNRESET
382   ERRNO_CASE(ECONNRESET);
383 #endif
384
385 #ifdef EDEADLK
386   ERRNO_CASE(EDEADLK);
387 #endif
388
389 #ifdef EDESTADDRREQ
390   ERRNO_CASE(EDESTADDRREQ);
391 #endif
392
393 #ifdef EDOM
394   ERRNO_CASE(EDOM);
395 #endif
396
397 #ifdef EDQUOT
398   ERRNO_CASE(EDQUOT);
399 #endif
400
401 #ifdef EEXIST
402   ERRNO_CASE(EEXIST);
403 #endif
404
405 #ifdef EFAULT
406   ERRNO_CASE(EFAULT);
407 #endif
408
409 #ifdef EFBIG
410   ERRNO_CASE(EFBIG);
411 #endif
412
413 #ifdef EHOSTUNREACH
414   ERRNO_CASE(EHOSTUNREACH);
415 #endif
416
417 #ifdef EIDRM
418   ERRNO_CASE(EIDRM);
419 #endif
420
421 #ifdef EILSEQ
422   ERRNO_CASE(EILSEQ);
423 #endif
424
425 #ifdef EINPROGRESS
426   ERRNO_CASE(EINPROGRESS);
427 #endif
428
429 #ifdef EINTR
430   ERRNO_CASE(EINTR);
431 #endif
432
433 #ifdef EINVAL
434   ERRNO_CASE(EINVAL);
435 #endif
436
437 #ifdef EIO
438   ERRNO_CASE(EIO);
439 #endif
440
441 #ifdef EISCONN
442   ERRNO_CASE(EISCONN);
443 #endif
444
445 #ifdef EISDIR
446   ERRNO_CASE(EISDIR);
447 #endif
448
449 #ifdef ELOOP
450   ERRNO_CASE(ELOOP);
451 #endif
452
453 #ifdef EMFILE
454   ERRNO_CASE(EMFILE);
455 #endif
456
457 #ifdef EMLINK
458   ERRNO_CASE(EMLINK);
459 #endif
460
461 #ifdef EMSGSIZE
462   ERRNO_CASE(EMSGSIZE);
463 #endif
464
465 #ifdef EMULTIHOP
466   ERRNO_CASE(EMULTIHOP);
467 #endif
468
469 #ifdef ENAMETOOLONG
470   ERRNO_CASE(ENAMETOOLONG);
471 #endif
472
473 #ifdef ENETDOWN
474   ERRNO_CASE(ENETDOWN);
475 #endif
476
477 #ifdef ENETRESET
478   ERRNO_CASE(ENETRESET);
479 #endif
480
481 #ifdef ENETUNREACH
482   ERRNO_CASE(ENETUNREACH);
483 #endif
484
485 #ifdef ENFILE
486   ERRNO_CASE(ENFILE);
487 #endif
488
489 #ifdef ENOBUFS
490   ERRNO_CASE(ENOBUFS);
491 #endif
492
493 #ifdef ENODATA
494   ERRNO_CASE(ENODATA);
495 #endif
496
497 #ifdef ENODEV
498   ERRNO_CASE(ENODEV);
499 #endif
500
501 #ifdef ENOENT
502   ERRNO_CASE(ENOENT);
503 #endif
504
505 #ifdef ENOEXEC
506   ERRNO_CASE(ENOEXEC);
507 #endif
508
509 #ifdef ENOLINK
510   ERRNO_CASE(ENOLINK);
511 #endif
512
513 #ifdef ENOLCK
514 # if ENOLINK != ENOLCK
515   ERRNO_CASE(ENOLCK);
516 # endif
517 #endif
518
519 #ifdef ENOMEM
520   ERRNO_CASE(ENOMEM);
521 #endif
522
523 #ifdef ENOMSG
524   ERRNO_CASE(ENOMSG);
525 #endif
526
527 #ifdef ENOPROTOOPT
528   ERRNO_CASE(ENOPROTOOPT);
529 #endif
530
531 #ifdef ENOSPC
532   ERRNO_CASE(ENOSPC);
533 #endif
534
535 #ifdef ENOSR
536   ERRNO_CASE(ENOSR);
537 #endif
538
539 #ifdef ENOSTR
540   ERRNO_CASE(ENOSTR);
541 #endif
542
543 #ifdef ENOSYS
544   ERRNO_CASE(ENOSYS);
545 #endif
546
547 #ifdef ENOTCONN
548   ERRNO_CASE(ENOTCONN);
549 #endif
550
551 #ifdef ENOTDIR
552   ERRNO_CASE(ENOTDIR);
553 #endif
554
555 #ifdef ENOTEMPTY
556   ERRNO_CASE(ENOTEMPTY);
557 #endif
558
559 #ifdef ENOTSOCK
560   ERRNO_CASE(ENOTSOCK);
561 #endif
562
563 #ifdef ENOTSUP
564   ERRNO_CASE(ENOTSUP);
565 #else
566 # ifdef EOPNOTSUPP
567   ERRNO_CASE(EOPNOTSUPP);
568 # endif
569 #endif
570
571 #ifdef ENOTTY
572   ERRNO_CASE(ENOTTY);
573 #endif
574
575 #ifdef ENXIO
576   ERRNO_CASE(ENXIO);
577 #endif
578
579
580 #ifdef EOVERFLOW
581   ERRNO_CASE(EOVERFLOW);
582 #endif
583
584 #ifdef EPERM
585   ERRNO_CASE(EPERM);
586 #endif
587
588 #ifdef EPIPE
589   ERRNO_CASE(EPIPE);
590 #endif
591
592 #ifdef EPROTO
593   ERRNO_CASE(EPROTO);
594 #endif
595
596 #ifdef EPROTONOSUPPORT
597   ERRNO_CASE(EPROTONOSUPPORT);
598 #endif
599
600 #ifdef EPROTOTYPE
601   ERRNO_CASE(EPROTOTYPE);
602 #endif
603
604 #ifdef ERANGE
605   ERRNO_CASE(ERANGE);
606 #endif
607
608 #ifdef EROFS
609   ERRNO_CASE(EROFS);
610 #endif
611
612 #ifdef ESPIPE
613   ERRNO_CASE(ESPIPE);
614 #endif
615
616 #ifdef ESRCH
617   ERRNO_CASE(ESRCH);
618 #endif
619
620 #ifdef ESTALE
621   ERRNO_CASE(ESTALE);
622 #endif
623
624 #ifdef ETIME
625   ERRNO_CASE(ETIME);
626 #endif
627
628 #ifdef ETIMEDOUT
629   ERRNO_CASE(ETIMEDOUT);
630 #endif
631
632 #ifdef ETXTBSY
633   ERRNO_CASE(ETXTBSY);
634 #endif
635
636 #ifdef EXDEV
637   ERRNO_CASE(EXDEV);
638 #endif
639
640 #ifdef WSAEINTR
641   ERRNO_CASE(WSAEINTR);
642 #endif
643
644 #ifdef WSAEBADF
645   ERRNO_CASE(WSAEBADF);
646 #endif
647
648 #ifdef WSAEACCES
649   ERRNO_CASE(WSAEACCES);
650 #endif
651
652 #ifdef WSAEFAULT
653   ERRNO_CASE(WSAEFAULT);
654 #endif
655
656 #ifdef WSAEINVAL
657   ERRNO_CASE(WSAEINVAL);
658 #endif
659
660 #ifdef WSAEMFILE
661   ERRNO_CASE(WSAEMFILE);
662 #endif
663
664 #ifdef WSAEWOULDBLOCK
665   ERRNO_CASE(WSAEWOULDBLOCK);
666 #endif
667
668 #ifdef WSAEINPROGRESS
669   ERRNO_CASE(WSAEINPROGRESS);
670 #endif
671
672 #ifdef WSAEALREADY
673   ERRNO_CASE(WSAEALREADY);
674 #endif
675
676 #ifdef WSAENOTSOCK
677   ERRNO_CASE(WSAENOTSOCK);
678 #endif
679
680 #ifdef WSAEDESTADDRREQ
681   ERRNO_CASE(WSAEDESTADDRREQ);
682 #endif
683
684 #ifdef WSAEMSGSIZE
685   ERRNO_CASE(WSAEMSGSIZE);
686 #endif
687
688 #ifdef WSAEPROTOTYPE
689   ERRNO_CASE(WSAEPROTOTYPE);
690 #endif
691
692 #ifdef WSAENOPROTOOPT
693   ERRNO_CASE(WSAENOPROTOOPT);
694 #endif
695
696 #ifdef WSAEPROTONOSUPPORT
697   ERRNO_CASE(WSAEPROTONOSUPPORT);
698 #endif
699
700 #ifdef WSAESOCKTNOSUPPORT
701   ERRNO_CASE(WSAESOCKTNOSUPPORT);
702 #endif
703
704 #ifdef WSAEOPNOTSUPP
705   ERRNO_CASE(WSAEOPNOTSUPP);
706 #endif
707
708 #ifdef WSAEPFNOSUPPORT
709   ERRNO_CASE(WSAEPFNOSUPPORT);
710 #endif
711
712 #ifdef WSAEAFNOSUPPORT
713   ERRNO_CASE(WSAEAFNOSUPPORT);
714 #endif
715
716 #ifdef WSAEADDRINUSE
717   ERRNO_CASE(WSAEADDRINUSE);
718 #endif
719
720 #ifdef WSAEADDRNOTAVAIL
721   ERRNO_CASE(WSAEADDRNOTAVAIL);
722 #endif
723
724 #ifdef WSAENETDOWN
725   ERRNO_CASE(WSAENETDOWN);
726 #endif
727
728 #ifdef WSAENETUNREACH
729   ERRNO_CASE(WSAENETUNREACH);
730 #endif
731
732 #ifdef WSAENETRESET
733   ERRNO_CASE(WSAENETRESET);
734 #endif
735
736 #ifdef WSAECONNABORTED
737   ERRNO_CASE(WSAECONNABORTED);
738 #endif
739
740 #ifdef WSAECONNRESET
741   ERRNO_CASE(WSAECONNRESET);
742 #endif
743
744 #ifdef WSAENOBUFS
745   ERRNO_CASE(WSAENOBUFS);
746 #endif
747
748 #ifdef WSAEISCONN
749   ERRNO_CASE(WSAEISCONN);
750 #endif
751
752 #ifdef WSAENOTCONN
753   ERRNO_CASE(WSAENOTCONN);
754 #endif
755
756 #ifdef WSAESHUTDOWN
757   ERRNO_CASE(WSAESHUTDOWN);
758 #endif
759
760 #ifdef WSAETOOMANYREFS
761   ERRNO_CASE(WSAETOOMANYREFS);
762 #endif
763
764 #ifdef WSAETIMEDOUT
765   ERRNO_CASE(WSAETIMEDOUT);
766 #endif
767
768 #ifdef WSAECONNREFUSED
769   ERRNO_CASE(WSAECONNREFUSED);
770 #endif
771
772 #ifdef WSAELOOP
773   ERRNO_CASE(WSAELOOP);
774 #endif
775
776 #ifdef WSAENAMETOOLONG
777   ERRNO_CASE(WSAENAMETOOLONG);
778 #endif
779
780 #ifdef WSAEHOSTDOWN
781   ERRNO_CASE(WSAEHOSTDOWN);
782 #endif
783
784 #ifdef WSAEHOSTUNREACH
785   ERRNO_CASE(WSAEHOSTUNREACH);
786 #endif
787
788 #ifdef WSAENOTEMPTY
789   ERRNO_CASE(WSAENOTEMPTY);
790 #endif
791
792 #ifdef WSAEPROCLIM
793   ERRNO_CASE(WSAEPROCLIM);
794 #endif
795
796 #ifdef WSAEUSERS
797   ERRNO_CASE(WSAEUSERS);
798 #endif
799
800 #ifdef WSAEDQUOT
801   ERRNO_CASE(WSAEDQUOT);
802 #endif
803
804 #ifdef WSAESTALE
805   ERRNO_CASE(WSAESTALE);
806 #endif
807
808 #ifdef WSAEREMOTE
809   ERRNO_CASE(WSAEREMOTE);
810 #endif
811
812 #ifdef WSASYSNOTREADY
813   ERRNO_CASE(WSASYSNOTREADY);
814 #endif
815
816 #ifdef WSAVERNOTSUPPORTED
817   ERRNO_CASE(WSAVERNOTSUPPORTED);
818 #endif
819
820 #ifdef WSANOTINITIALISED
821   ERRNO_CASE(WSANOTINITIALISED);
822 #endif
823
824 #ifdef WSAEDISCON
825   ERRNO_CASE(WSAEDISCON);
826 #endif
827
828 #ifdef WSAENOMORE
829   ERRNO_CASE(WSAENOMORE);
830 #endif
831
832 #ifdef WSAECANCELLED
833   ERRNO_CASE(WSAECANCELLED);
834 #endif
835
836 #ifdef WSAEINVALIDPROCTABLE
837   ERRNO_CASE(WSAEINVALIDPROCTABLE);
838 #endif
839
840 #ifdef WSAEINVALIDPROVIDER
841   ERRNO_CASE(WSAEINVALIDPROVIDER);
842 #endif
843
844 #ifdef WSAEPROVIDERFAILEDINIT
845   ERRNO_CASE(WSAEPROVIDERFAILEDINIT);
846 #endif
847
848 #ifdef WSASYSCALLFAILURE
849   ERRNO_CASE(WSASYSCALLFAILURE);
850 #endif
851
852 #ifdef WSASERVICE_NOT_FOUND
853   ERRNO_CASE(WSASERVICE_NOT_FOUND);
854 #endif
855
856 #ifdef WSATYPE_NOT_FOUND
857   ERRNO_CASE(WSATYPE_NOT_FOUND);
858 #endif
859
860 #ifdef WSA_E_NO_MORE
861   ERRNO_CASE(WSA_E_NO_MORE);
862 #endif
863
864 #ifdef WSA_E_CANCELLED
865   ERRNO_CASE(WSA_E_CANCELLED);
866 #endif
867
868   default: return "";
869   }
870 }
871
872 const char *signo_string(int signo) {
873 #define SIGNO_CASE(e)  case e: return #e;
874   switch (signo) {
875
876 #ifdef SIGHUP
877   SIGNO_CASE(SIGHUP);
878 #endif
879
880 #ifdef SIGINT
881   SIGNO_CASE(SIGINT);
882 #endif
883
884 #ifdef SIGQUIT
885   SIGNO_CASE(SIGQUIT);
886 #endif
887
888 #ifdef SIGILL
889   SIGNO_CASE(SIGILL);
890 #endif
891
892 #ifdef SIGTRAP
893   SIGNO_CASE(SIGTRAP);
894 #endif
895
896 #ifdef SIGABRT
897   SIGNO_CASE(SIGABRT);
898 #endif
899
900 #ifdef SIGIOT
901 # if SIGABRT != SIGIOT
902   SIGNO_CASE(SIGIOT);
903 # endif
904 #endif
905
906 #ifdef SIGBUS
907   SIGNO_CASE(SIGBUS);
908 #endif
909
910 #ifdef SIGFPE
911   SIGNO_CASE(SIGFPE);
912 #endif
913
914 #ifdef SIGKILL
915   SIGNO_CASE(SIGKILL);
916 #endif
917
918 #ifdef SIGUSR1
919   SIGNO_CASE(SIGUSR1);
920 #endif
921
922 #ifdef SIGSEGV
923   SIGNO_CASE(SIGSEGV);
924 #endif
925
926 #ifdef SIGUSR2
927   SIGNO_CASE(SIGUSR2);
928 #endif
929
930 #ifdef SIGPIPE
931   SIGNO_CASE(SIGPIPE);
932 #endif
933
934 #ifdef SIGALRM
935   SIGNO_CASE(SIGALRM);
936 #endif
937
938   SIGNO_CASE(SIGTERM);
939
940 #ifdef SIGCHLD
941   SIGNO_CASE(SIGCHLD);
942 #endif
943
944 #ifdef SIGSTKFLT
945   SIGNO_CASE(SIGSTKFLT);
946 #endif
947
948
949 #ifdef SIGCONT
950   SIGNO_CASE(SIGCONT);
951 #endif
952
953 #ifdef SIGSTOP
954   SIGNO_CASE(SIGSTOP);
955 #endif
956
957 #ifdef SIGTSTP
958   SIGNO_CASE(SIGTSTP);
959 #endif
960
961 #ifdef SIGTTIN
962   SIGNO_CASE(SIGTTIN);
963 #endif
964
965 #ifdef SIGTTOU
966   SIGNO_CASE(SIGTTOU);
967 #endif
968
969 #ifdef SIGURG
970   SIGNO_CASE(SIGURG);
971 #endif
972
973 #ifdef SIGXCPU
974   SIGNO_CASE(SIGXCPU);
975 #endif
976
977 #ifdef SIGXFSZ
978   SIGNO_CASE(SIGXFSZ);
979 #endif
980
981 #ifdef SIGVTALRM
982   SIGNO_CASE(SIGVTALRM);
983 #endif
984
985 #ifdef SIGPROF
986   SIGNO_CASE(SIGPROF);
987 #endif
988
989 #ifdef SIGWINCH
990   SIGNO_CASE(SIGWINCH);
991 #endif
992
993 #ifdef SIGIO
994   SIGNO_CASE(SIGIO);
995 #endif
996
997 #ifdef SIGPOLL
998 # if SIGPOLL != SIGIO
999   SIGNO_CASE(SIGPOLL);
1000 # endif
1001 #endif
1002
1003 #ifdef SIGLOST
1004   SIGNO_CASE(SIGLOST);
1005 #endif
1006
1007 #ifdef SIGPWR
1008 # if SIGPWR != SIGLOST
1009   SIGNO_CASE(SIGPWR);
1010 # endif
1011 #endif
1012
1013 #ifdef SIGSYS
1014   SIGNO_CASE(SIGSYS);
1015 #endif
1016
1017   default: return "";
1018   }
1019 }
1020
1021
1022 Local<Value> ErrnoException(int errorno,
1023                             const char *syscall,
1024                             const char *msg,
1025                             const char *path) {
1026   Local<Value> e;
1027   Local<String> estring = String::NewSymbol(errno_string(errorno));
1028   if (!msg[0]) {
1029 #ifdef __POSIX__
1030     msg = strerror(errorno);
1031 #else // __MINGW32__
1032     msg = winapi_strerror(errorno);
1033 #endif
1034   }
1035   Local<String> message = String::NewSymbol(msg);
1036
1037   Local<String> cons1 = String::Concat(estring, String::NewSymbol(", "));
1038   Local<String> cons2 = String::Concat(cons1, message);
1039
1040   if (errno_symbol.IsEmpty()) {
1041     syscall_symbol = NODE_PSYMBOL("syscall");
1042     errno_symbol = NODE_PSYMBOL("errno");
1043     errpath_symbol = NODE_PSYMBOL("path");
1044     code_symbol = NODE_PSYMBOL("code");
1045   }
1046
1047   if (path) {
1048     Local<String> cons3 = String::Concat(cons2, String::NewSymbol(" '"));
1049     Local<String> cons4 = String::Concat(cons3, String::New(path));
1050     Local<String> cons5 = String::Concat(cons4, String::NewSymbol("'"));
1051     e = Exception::Error(cons5);
1052   } else {
1053     e = Exception::Error(cons2);
1054   }
1055
1056   Local<Object> obj = e->ToObject();
1057
1058   obj->Set(errno_symbol, Integer::New(errorno));
1059   obj->Set(code_symbol, estring);
1060   if (path) obj->Set(errpath_symbol, String::New(path));
1061   if (syscall) obj->Set(syscall_symbol, String::NewSymbol(syscall));
1062   return e;
1063 }
1064
1065
1066 Handle<Value> FromConstructorTemplate(Persistent<FunctionTemplate>& t,
1067                                       const Arguments& args) {
1068   HandleScope scope;
1069
1070   const int argc = args.Length();
1071   Local<Value>* argv = new Local<Value>[argc];
1072
1073   for (int i = 0; i < argc; ++i) {
1074     argv[i] = args[i];
1075   }
1076
1077   Local<Object> instance = t->GetFunction()->NewInstance(argc, argv);
1078
1079   delete[] argv;
1080
1081   return scope.Close(instance);
1082 }
1083
1084
1085 enum encoding ParseEncoding(Handle<Value> encoding_v, enum encoding _default) {
1086   HandleScope scope;
1087
1088   if (!encoding_v->IsString()) return _default;
1089
1090   String::Utf8Value encoding(encoding_v->ToString());
1091
1092   if (strcasecmp(*encoding, "utf8") == 0) {
1093     return UTF8;
1094   } else if (strcasecmp(*encoding, "utf-8") == 0) {
1095     return UTF8;
1096   } else if (strcasecmp(*encoding, "ascii") == 0) {
1097     return ASCII;
1098   } else if (strcasecmp(*encoding, "base64") == 0) {
1099     return BASE64;
1100   } else if (strcasecmp(*encoding, "ucs2") == 0) {
1101     return UCS2;
1102   } else if (strcasecmp(*encoding, "ucs-2") == 0) {
1103     return UCS2;
1104   } else if (strcasecmp(*encoding, "binary") == 0) {
1105     return BINARY;
1106   } else if (strcasecmp(*encoding, "hex") == 0) {
1107     return HEX;
1108   } else if (strcasecmp(*encoding, "raw") == 0) {
1109     fprintf(stderr, "'raw' (array of integers) has been removed. "
1110                     "Use 'binary'.\n");
1111     return BINARY;
1112   } else if (strcasecmp(*encoding, "raws") == 0) {
1113     fprintf(stderr, "'raws' encoding has been renamed to 'binary'. "
1114                     "Please update your code.\n");
1115     return BINARY;
1116   } else {
1117     return _default;
1118   }
1119 }
1120
1121 Local<Value> Encode(const void *buf, size_t len, enum encoding encoding) {
1122   HandleScope scope;
1123
1124   if (!len) return scope.Close(String::Empty());
1125
1126   if (encoding == BINARY) {
1127     const unsigned char *cbuf = static_cast<const unsigned char*>(buf);
1128     uint16_t * twobytebuf = new uint16_t[len];
1129     for (size_t i = 0; i < len; i++) {
1130       // XXX is the following line platform independent?
1131       twobytebuf[i] = cbuf[i];
1132     }
1133     Local<String> chunk = String::New(twobytebuf, len);
1134     delete [] twobytebuf; // TODO use ExternalTwoByteString?
1135     return scope.Close(chunk);
1136   }
1137
1138   // utf8 or ascii encoding
1139   Local<String> chunk = String::New((const char*)buf, len);
1140   return scope.Close(chunk);
1141 }
1142
1143 // Returns -1 if the handle was not valid for decoding
1144 ssize_t DecodeBytes(v8::Handle<v8::Value> val, enum encoding encoding) {
1145   HandleScope scope;
1146
1147   if (val->IsArray()) {
1148     fprintf(stderr, "'raw' encoding (array of integers) has been removed. "
1149                     "Use 'binary'.\n");
1150     assert(0);
1151     return -1;
1152   }
1153
1154   Local<String> str = val->ToString();
1155
1156   if (encoding == UTF8) return str->Utf8Length();
1157   else if (encoding == UCS2) return str->Length() * 2;
1158   else if (encoding == HEX) return str->Length() / 2;
1159
1160   return str->Length();
1161 }
1162
1163 #ifndef MIN
1164 # define MIN(a, b) ((a) < (b) ? (a) : (b))
1165 #endif
1166
1167 // Returns number of bytes written.
1168 ssize_t DecodeWrite(char *buf,
1169                     size_t buflen,
1170                     v8::Handle<v8::Value> val,
1171                     enum encoding encoding) {
1172   HandleScope scope;
1173
1174   // XXX
1175   // A lot of improvement can be made here. See:
1176   // http://code.google.com/p/v8/issues/detail?id=270
1177   // http://groups.google.com/group/v8-dev/browse_thread/thread/dba28a81d9215291/ece2b50a3b4022c
1178   // http://groups.google.com/group/v8-users/browse_thread/thread/1f83b0ba1f0a611
1179
1180   if (val->IsArray()) {
1181     fprintf(stderr, "'raw' encoding (array of integers) has been removed. "
1182                     "Use 'binary'.\n");
1183     assert(0);
1184     return -1;
1185   }
1186
1187   Local<String> str = val->ToString();
1188
1189   if (encoding == UTF8) {
1190     str->WriteUtf8(buf, buflen, NULL, String::HINT_MANY_WRITES_EXPECTED);
1191     return buflen;
1192   }
1193
1194   if (encoding == ASCII) {
1195     str->WriteAscii(buf, 0, buflen, String::HINT_MANY_WRITES_EXPECTED);
1196     return buflen;
1197   }
1198
1199   // THIS IS AWFUL!!! FIXME
1200
1201   assert(encoding == BINARY);
1202
1203   uint16_t * twobytebuf = new uint16_t[buflen];
1204
1205   str->Write(twobytebuf, 0, buflen, String::HINT_MANY_WRITES_EXPECTED);
1206
1207   for (size_t i = 0; i < buflen; i++) {
1208     unsigned char *b = reinterpret_cast<unsigned char*>(&twobytebuf[i]);
1209     assert(b[1] == 0);
1210     buf[i] = b[0];
1211   }
1212
1213   delete [] twobytebuf;
1214
1215   return buflen;
1216 }
1217
1218
1219 void DisplayExceptionLine (TryCatch &try_catch) {
1220   HandleScope scope;
1221
1222   Handle<Message> message = try_catch.Message();
1223
1224   node::Stdio::DisableRawMode(STDIN_FILENO);
1225   fprintf(stderr, "\n");
1226
1227   if (!message.IsEmpty()) {
1228     // Print (filename):(line number): (message).
1229     String::Utf8Value filename(message->GetScriptResourceName());
1230     const char* filename_string = *filename;
1231     int linenum = message->GetLineNumber();
1232     fprintf(stderr, "%s:%i\n", filename_string, linenum);
1233     // Print line of source code.
1234     String::Utf8Value sourceline(message->GetSourceLine());
1235     const char* sourceline_string = *sourceline;
1236
1237     // HACK HACK HACK
1238     //
1239     // FIXME
1240     //
1241     // Because of how CommonJS modules work, all scripts are wrapped with a
1242     // "function (function (exports, __filename, ...) {"
1243     // to provide script local variables.
1244     //
1245     // When reporting errors on the first line of a script, this wrapper
1246     // function is leaked to the user. This HACK is to remove it. The length
1247     // of the wrapper is 62. That wrapper is defined in src/node.js
1248     //
1249     // If that wrapper is ever changed, then this number also has to be
1250     // updated. Or - someone could clean this up so that the two peices
1251     // don't need to be changed.
1252     //
1253     // Even better would be to get support into V8 for wrappers that
1254     // shouldn't be reported to users.
1255     int offset = linenum == 1 ? 62 : 0;
1256
1257     fprintf(stderr, "%s\n", sourceline_string + offset);
1258     // Print wavy underline (GetUnderline is deprecated).
1259     int start = message->GetStartColumn();
1260     for (int i = offset; i < start; i++) {
1261       fprintf(stderr, " ");
1262     }
1263     int end = message->GetEndColumn();
1264     for (int i = start; i < end; i++) {
1265       fprintf(stderr, "^");
1266     }
1267     fprintf(stderr, "\n");
1268   }
1269 }
1270
1271
1272 static void ReportException(TryCatch &try_catch, bool show_line) {
1273   HandleScope scope;
1274   Handle<Message> message = try_catch.Message();
1275
1276   if (show_line) DisplayExceptionLine(try_catch);
1277
1278   String::Utf8Value trace(try_catch.StackTrace());
1279
1280   if (trace.length() > 0) {
1281     fprintf(stderr, "%s\n", *trace);
1282   } else {
1283     // this really only happens for RangeErrors, since they're the only
1284     // kind that won't have all this info in the trace.
1285     Local<Value> er = try_catch.Exception();
1286     String::Utf8Value msg(!er->IsObject() ? er->ToString()
1287                          : er->ToObject()->Get(String::New("message"))->ToString());
1288     fprintf(stderr, "%s\n", *msg);
1289   }
1290
1291   fflush(stderr);
1292 }
1293
1294 // Executes a str within the current v8 context.
1295 Local<Value> ExecuteString(Handle<String> source, Handle<Value> filename) {
1296   HandleScope scope;
1297   TryCatch try_catch;
1298
1299   Local<v8::Script> script = v8::Script::Compile(source, filename);
1300   if (script.IsEmpty()) {
1301     ReportException(try_catch, true);
1302     exit(1);
1303   }
1304
1305   Local<Value> result = script->Run();
1306   if (result.IsEmpty()) {
1307     ReportException(try_catch, true);
1308     exit(1);
1309   }
1310
1311   return scope.Close(result);
1312 }
1313
1314
1315 static Handle<Value> Chdir(const Arguments& args) {
1316   HandleScope scope;
1317
1318   if (args.Length() != 1 || !args[0]->IsString()) {
1319     return ThrowException(Exception::Error(String::New("Bad argument.")));
1320   }
1321
1322   String::Utf8Value path(args[0]->ToString());
1323
1324   int r = chdir(*path);
1325
1326   if (r != 0) {
1327     return ThrowException(Exception::Error(String::New(strerror(errno))));
1328   }
1329
1330   return Undefined();
1331 }
1332
1333 static Handle<Value> Cwd(const Arguments& args) {
1334   HandleScope scope;
1335   assert(args.Length() == 0);
1336
1337   char *r = getcwd(getbuf, ARRAY_SIZE(getbuf) - 1);
1338   if (r == NULL) {
1339     return ThrowException(Exception::Error(String::New(strerror(errno))));
1340   }
1341
1342   getbuf[ARRAY_SIZE(getbuf) - 1] = '\0';
1343   Local<String> cwd = String::New(r);
1344
1345   return scope.Close(cwd);
1346 }
1347
1348
1349 #ifdef __POSIX__
1350
1351 static Handle<Value> Umask(const Arguments& args){
1352   HandleScope scope;
1353   unsigned int old;
1354
1355   if(args.Length() < 1 || args[0]->IsUndefined()) {
1356     old = umask(0);
1357     umask((mode_t)old);
1358
1359   } else if(!args[0]->IsInt32() && !args[0]->IsString()) {
1360     return ThrowException(Exception::TypeError(
1361           String::New("argument must be an integer or octal string.")));
1362
1363   } else {
1364     int oct;
1365     if(args[0]->IsInt32()) {
1366       oct = args[0]->Uint32Value();
1367     } else {
1368       oct = 0;
1369       String::Utf8Value str(args[0]);
1370
1371       // Parse the octal string.
1372       for (int i = 0; i < str.length(); i++) {
1373         char c = (*str)[i];
1374         if (c > '7' || c < '0') {
1375           return ThrowException(Exception::TypeError(
1376                 String::New("invalid octal string")));
1377         }
1378         oct *= 8;
1379         oct += c - '0';
1380       }
1381     }
1382     old = umask(static_cast<mode_t>(oct));
1383   }
1384
1385   return scope.Close(Uint32::New(old));
1386 }
1387
1388
1389 static Handle<Value> GetUid(const Arguments& args) {
1390   HandleScope scope;
1391   assert(args.Length() == 0);
1392   int uid = getuid();
1393   return scope.Close(Integer::New(uid));
1394 }
1395
1396 static Handle<Value> GetGid(const Arguments& args) {
1397   HandleScope scope;
1398   assert(args.Length() == 0);
1399   int gid = getgid();
1400   return scope.Close(Integer::New(gid));
1401 }
1402
1403
1404 static Handle<Value> SetGid(const Arguments& args) {
1405   HandleScope scope;
1406
1407   if (args.Length() < 1) {
1408     return ThrowException(Exception::Error(
1409       String::New("setgid requires 1 argument")));
1410   }
1411
1412   int gid;
1413
1414   if (args[0]->IsNumber()) {
1415     gid = args[0]->Int32Value();
1416   } else if (args[0]->IsString()) {
1417     String::Utf8Value grpnam(args[0]->ToString());
1418     struct group grp, *grpp = NULL;
1419     int err;
1420
1421     if ((err = getgrnam_r(*grpnam, &grp, getbuf, ARRAY_SIZE(getbuf), &grpp)) ||
1422         grpp == NULL) {
1423       return ThrowException(ErrnoException(errno, "getgrnam_r"));
1424     }
1425
1426     gid = grpp->gr_gid;
1427   } else {
1428     return ThrowException(Exception::Error(
1429       String::New("setgid argument must be a number or a string")));
1430   }
1431
1432   int result;
1433   if ((result = setgid(gid)) != 0) {
1434     return ThrowException(ErrnoException(errno, "setgid"));
1435   }
1436   return Undefined();
1437 }
1438
1439 static Handle<Value> SetUid(const Arguments& args) {
1440   HandleScope scope;
1441
1442   if (args.Length() < 1) {
1443     return ThrowException(Exception::Error(
1444           String::New("setuid requires 1 argument")));
1445   }
1446
1447   int uid;
1448
1449   if (args[0]->IsNumber()) {
1450     uid = args[0]->Int32Value();
1451   } else if (args[0]->IsString()) {
1452     String::Utf8Value pwnam(args[0]->ToString());
1453     struct passwd pwd, *pwdp = NULL;
1454     int err;
1455
1456     if ((err = getpwnam_r(*pwnam, &pwd, getbuf, ARRAY_SIZE(getbuf), &pwdp)) ||
1457         pwdp == NULL) {
1458       return ThrowException(ErrnoException(errno, "getpwnam_r"));
1459     }
1460
1461     uid = pwdp->pw_uid;
1462   } else {
1463     return ThrowException(Exception::Error(
1464       String::New("setuid argument must be a number or a string")));
1465   }
1466
1467   int result;
1468   if ((result = setuid(uid)) != 0) {
1469     return ThrowException(ErrnoException(errno, "setuid"));
1470   }
1471   return Undefined();
1472 }
1473
1474 #endif // __POSIX__
1475
1476
1477 v8::Handle<v8::Value> Exit(const v8::Arguments& args) {
1478   HandleScope scope;
1479   exit(args[0]->IntegerValue());
1480   return Undefined();
1481 }
1482
1483
1484 static void CheckStatus(EV_P_ ev_timer *watcher, int revents) {
1485   assert(watcher == &gc_timer);
1486   assert(revents == EV_TIMEOUT);
1487
1488   // check memory
1489   size_t rss, vsize;
1490   if (!ev_is_active(&gc_idle) && Platform::GetMemory(&rss, &vsize) == 0) {
1491     if (rss > 1024*1024*128) {
1492       // larger than 128 megs, just start the idle watcher
1493       ev_idle_start(EV_A_ &gc_idle);
1494       return;
1495     }
1496   }
1497
1498   double d = ev_now(EV_DEFAULT_UC) - TICK_TIME(3);
1499
1500   //printfb("timer d = %f\n", d);
1501
1502   if (d  >= GC_WAIT_TIME - 1.) {
1503     //fprintf(stderr, "start idle\n");
1504     ev_idle_start(EV_A_ &gc_idle);
1505   }
1506 }
1507
1508 static Handle<Value> Uptime(const Arguments& args) {
1509   HandleScope scope;
1510   assert(args.Length() == 0);
1511
1512   double uptime =  Platform::GetUptime(true);
1513
1514   if (uptime < 0) {
1515     return Undefined();
1516   }
1517
1518   return scope.Close(Number::New(uptime));
1519 }
1520
1521 v8::Handle<v8::Value> MemoryUsage(const v8::Arguments& args) {
1522   HandleScope scope;
1523   assert(args.Length() == 0);
1524
1525   size_t rss, vsize;
1526
1527   int r = Platform::GetMemory(&rss, &vsize);
1528
1529   if (r != 0) {
1530     return ThrowException(Exception::Error(String::New(strerror(errno))));
1531   }
1532
1533   Local<Object> info = Object::New();
1534
1535   if (rss_symbol.IsEmpty()) {
1536     rss_symbol = NODE_PSYMBOL("rss");
1537     vsize_symbol = NODE_PSYMBOL("vsize");
1538     heap_total_symbol = NODE_PSYMBOL("heapTotal");
1539     heap_used_symbol = NODE_PSYMBOL("heapUsed");
1540   }
1541
1542   info->Set(rss_symbol, Integer::NewFromUnsigned(rss));
1543   info->Set(vsize_symbol, Integer::NewFromUnsigned(vsize));
1544
1545   // V8 memory usage
1546   HeapStatistics v8_heap_stats;
1547   V8::GetHeapStatistics(&v8_heap_stats);
1548   info->Set(heap_total_symbol,
1549             Integer::NewFromUnsigned(v8_heap_stats.total_heap_size()));
1550   info->Set(heap_used_symbol,
1551             Integer::NewFromUnsigned(v8_heap_stats.used_heap_size()));
1552
1553   return scope.Close(info);
1554 }
1555
1556
1557 #ifdef __POSIX__
1558
1559 Handle<Value> Kill(const Arguments& args) {
1560   HandleScope scope;
1561
1562   if (args.Length() != 2) {
1563     return ThrowException(Exception::Error(String::New("Bad argument.")));
1564   }
1565
1566   pid_t pid = args[0]->IntegerValue();
1567   int sig = args[1]->Int32Value();
1568   int r = kill(pid, sig);
1569
1570   if (r != 0) return ThrowException(ErrnoException(errno, "kill"));
1571
1572   return Undefined();
1573 }
1574
1575
1576 typedef void (*extInit)(Handle<Object> exports);
1577
1578 // DLOpen is node.dlopen(). Used to load 'module.node' dynamically shared
1579 // objects.
1580 Handle<Value> DLOpen(const v8::Arguments& args) {
1581   HandleScope scope;
1582
1583   if (args.Length() < 2) return Undefined();
1584
1585   String::Utf8Value filename(args[0]->ToString()); // Cast
1586   Local<Object> target = args[1]->ToObject(); // Cast
1587
1588   // Actually call dlopen().
1589   // FIXME: This is a blocking function and should be called asynchronously!
1590   // This function should be moved to file.cc and use libeio to make this
1591   // system call.
1592   void *handle = dlopen(*filename, RTLD_LAZY);
1593
1594   // Handle errors.
1595   if (handle == NULL) {
1596     Local<Value> exception = Exception::Error(String::New(dlerror()));
1597     return ThrowException(exception);
1598   }
1599
1600   String::Utf8Value symbol(args[0]->ToString());
1601   char *symstr = NULL;
1602   {
1603     char *sym = *symbol;
1604     char *p = strrchr(sym, '/');
1605     if (p != NULL) {
1606       sym = p+1;
1607     }
1608
1609     p = strrchr(sym, '.');
1610     if (p != NULL) {
1611       *p = '\0';
1612     }
1613
1614     size_t slen = strlen(sym);
1615     symstr = static_cast<char*>(calloc(1, slen + sizeof("_module") + 1));
1616     memcpy(symstr, sym, slen);
1617     memcpy(symstr+slen, "_module", sizeof("_module") + 1);
1618   }
1619
1620   // Get the init() function from the dynamically shared object.
1621   node_module_struct *mod = static_cast<node_module_struct *>(dlsym(handle, symstr));
1622   free(symstr);
1623   // Error out if not found.
1624   if (mod == NULL) {
1625     /* Start Compatibility hack: Remove once everyone is using NODE_MODULE macro */
1626     node_module_struct compat_mod;
1627     mod = &compat_mod;
1628     mod->version = NODE_MODULE_VERSION;
1629
1630     void *init_handle = dlsym(handle, "init");
1631     if (init_handle == NULL) {
1632       dlclose(handle);
1633       Local<Value> exception =
1634         Exception::Error(String::New("No module symbol found in module."));
1635       return ThrowException(exception);
1636     }
1637     mod->register_func = (extInit)(init_handle);
1638     /* End Compatibility hack */
1639   }
1640
1641   if (mod->version != NODE_MODULE_VERSION) {
1642     Local<Value> exception =
1643       Exception::Error(String::New("Module version mismatch, refusing to load."));
1644     return ThrowException(exception);
1645   }
1646
1647   // Execute the C++ module
1648   mod->register_func(target);
1649
1650   // Tell coverity that 'handle' should not be freed when we return.
1651   // coverity[leaked_storage]
1652   return Undefined();
1653 }
1654
1655 #endif // __POSIX__
1656
1657
1658 // TODO remove me before 0.4
1659 Handle<Value> Compile(const Arguments& args) {
1660   HandleScope scope;
1661
1662
1663   if (args.Length() < 2) {
1664     return ThrowException(Exception::TypeError(
1665           String::New("needs two arguments.")));
1666   }
1667
1668   static bool shown_error_message = false;
1669
1670   if (!shown_error_message) {
1671     shown_error_message = true;
1672     fprintf(stderr, "(node) process.compile should not be used. "
1673                     "Use require('vm').runInThisContext instead.\n");
1674   }
1675
1676   Local<String> source = args[0]->ToString();
1677   Local<String> filename = args[1]->ToString();
1678
1679   TryCatch try_catch;
1680
1681   Local<v8::Script> script = v8::Script::Compile(source, filename);
1682   if (try_catch.HasCaught()) {
1683     // Hack because I can't get a proper stacktrace on SyntaxError
1684     ReportException(try_catch, true);
1685     exit(1);
1686   }
1687
1688   Local<Value> result = script->Run();
1689   if (try_catch.HasCaught()) {
1690     ReportException(try_catch, false);
1691     exit(1);
1692   }
1693
1694   return scope.Close(result);
1695 }
1696
1697 static void OnFatalError(const char* location, const char* message) {
1698   if (location) {
1699     fprintf(stderr, "FATAL ERROR: %s %s\n", location, message);
1700   } else {
1701     fprintf(stderr, "FATAL ERROR: %s\n", message);
1702   }
1703   exit(1);
1704 }
1705
1706 static int uncaught_exception_counter = 0;
1707
1708 void FatalException(TryCatch &try_catch) {
1709   HandleScope scope;
1710
1711   // Check if uncaught_exception_counter indicates a recursion
1712   if (uncaught_exception_counter > 0) {
1713     ReportException(try_catch, true);
1714     exit(1);
1715   }
1716
1717   if (listeners_symbol.IsEmpty()) {
1718     listeners_symbol = NODE_PSYMBOL("listeners");
1719     uncaught_exception_symbol = NODE_PSYMBOL("uncaughtException");
1720     emit_symbol = NODE_PSYMBOL("emit");
1721   }
1722
1723   Local<Value> listeners_v = process->Get(listeners_symbol);
1724   assert(listeners_v->IsFunction());
1725
1726   Local<Function> listeners = Local<Function>::Cast(listeners_v);
1727
1728   Local<String> uncaught_exception_symbol_l = Local<String>::New(uncaught_exception_symbol);
1729   Local<Value> argv[1] = { uncaught_exception_symbol_l  };
1730   Local<Value> ret = listeners->Call(process, 1, argv);
1731
1732   assert(ret->IsArray());
1733
1734   Local<Array> listener_array = Local<Array>::Cast(ret);
1735
1736   uint32_t length = listener_array->Length();
1737   // Report and exit if process has no "uncaughtException" listener
1738   if (length == 0) {
1739     ReportException(try_catch, true);
1740     exit(1);
1741   }
1742
1743   // Otherwise fire the process "uncaughtException" event
1744   Local<Value> emit_v = process->Get(emit_symbol);
1745   assert(emit_v->IsFunction());
1746
1747   Local<Function> emit = Local<Function>::Cast(emit_v);
1748
1749   Local<Value> error = try_catch.Exception();
1750   Local<Value> event_argv[2] = { uncaught_exception_symbol_l, error };
1751
1752   uncaught_exception_counter++;
1753   emit->Call(process, 2, event_argv);
1754   // Decrement so we know if the next exception is a recursion or not
1755   uncaught_exception_counter--;
1756 }
1757
1758
1759 static ev_async debug_watcher;
1760
1761 static void DebugMessageCallback(EV_P_ ev_async *watcher, int revents) {
1762   HandleScope scope;
1763   assert(watcher == &debug_watcher);
1764   assert(revents == EV_ASYNC);
1765   Debug::ProcessDebugMessages();
1766 }
1767
1768 static void DebugMessageDispatch(void) {
1769   // This function is called from V8's debug thread when a debug TCP client
1770   // has sent a message.
1771
1772   // Send a signal to our main thread saying that it should enter V8 to
1773   // handle the message.
1774   ev_async_send(EV_DEFAULT_UC_ &debug_watcher);
1775 }
1776
1777 static void DebugBreakMessageHandler(const Debug::Message& message) {
1778   // do nothing with debug messages.
1779   // The message handler will get changed by DebuggerAgent::CreateSession in
1780   // debug-agent.cc of v8/src when a new session is created
1781 }
1782
1783
1784 Persistent<Object> binding_cache;
1785
1786 static Handle<Value> Binding(const Arguments& args) {
1787   HandleScope scope;
1788
1789   Local<String> module = args[0]->ToString();
1790   String::Utf8Value module_v(module);
1791   node_module_struct* modp;
1792
1793   if (binding_cache.IsEmpty()) {
1794     binding_cache = Persistent<Object>::New(Object::New());
1795   }
1796
1797   Local<Object> exports;
1798
1799   if (binding_cache->Has(module)) {
1800     exports = binding_cache->Get(module)->ToObject();
1801
1802   } else if ((modp = get_builtin_module(*module_v)) != NULL) {
1803     exports = Object::New();
1804     modp->register_func(exports);
1805     binding_cache->Set(module, exports);
1806
1807   } else if (!strcmp(*module_v, "constants")) {
1808     exports = Object::New();
1809     DefineConstants(exports);
1810     binding_cache->Set(module, exports);
1811
1812   } else if (!strcmp(*module_v, "io_watcher")) {
1813     exports = Object::New();
1814     IOWatcher::Initialize(exports);
1815     binding_cache->Set(module, exports);
1816
1817   } else if (!strcmp(*module_v, "timer")) {
1818     exports = Object::New();
1819     Timer::Initialize(exports);
1820     binding_cache->Set(module, exports);
1821
1822   } else if (!strcmp(*module_v, "natives")) {
1823     exports = Object::New();
1824     DefineJavaScript(exports);
1825     binding_cache->Set(module, exports);
1826
1827   } else {
1828
1829     return ThrowException(Exception::Error(String::New("No such module")));
1830   }
1831
1832   return scope.Close(exports);
1833 }
1834
1835
1836 static Handle<Value> ProcessTitleGetter(Local<String> property,
1837                                         const AccessorInfo& info) {
1838   HandleScope scope;
1839   int len;
1840   const char *s = Platform::GetProcessTitle(&len);
1841   return scope.Close(s ? String::New(s, len) : String::Empty());
1842 }
1843
1844
1845 static void ProcessTitleSetter(Local<String> property,
1846                                Local<Value> value,
1847                                const AccessorInfo& info) {
1848   HandleScope scope;
1849   String::Utf8Value title(value->ToString());
1850   Platform::SetProcessTitle(*title);
1851 }
1852
1853
1854 static Handle<Value> EnvGetter(Local<String> property,
1855                                const AccessorInfo& info) {
1856   String::Utf8Value key(property);
1857   const char* val = getenv(*key);
1858   if (val) {
1859     HandleScope scope;
1860     return scope.Close(String::New(val));
1861   }
1862   return Undefined();
1863 }
1864
1865
1866 static bool ENV_warning = false;
1867 static Handle<Value> EnvGetterWarn(Local<String> property,
1868                                    const AccessorInfo& info) {
1869   if (!ENV_warning) {
1870     ENV_warning = true;
1871     fprintf(stderr, "(node) Use process.env instead of process.ENV\r\n");
1872   }
1873   return EnvGetter(property, info);
1874 }
1875
1876
1877 static Handle<Value> EnvSetter(Local<String> property,
1878                                Local<Value> value,
1879                                const AccessorInfo& info) {
1880   String::Utf8Value key(property);
1881   String::Utf8Value val(value);
1882 #ifdef __POSIX__
1883   setenv(*key, *val, 1);
1884 #else  // __WIN32__
1885   NO_IMPL_MSG(setenv)
1886 #endif
1887   return value;
1888 }
1889
1890
1891 static Handle<Integer> EnvQuery(Local<String> property,
1892                                 const AccessorInfo& info) {
1893   String::Utf8Value key(property);
1894   if (getenv(*key)) {
1895     HandleScope scope;
1896     return scope.Close(Integer::New(None));
1897   }
1898   return Handle<Integer>();
1899 }
1900
1901
1902 static Handle<Boolean> EnvDeleter(Local<String> property,
1903                                   const AccessorInfo& info) {
1904   String::Utf8Value key(property);
1905   if (getenv(*key)) {
1906 #ifdef __POSIX__
1907     unsetenv(*key);     // prototyped as `void unsetenv(const char*)` on some platforms
1908 #else
1909     NO_IMPL_MSG(unsetenv)
1910 #endif
1911     return True();
1912   }
1913   return False();
1914 }
1915
1916
1917 static Handle<Array> EnvEnumerator(const AccessorInfo& info) {
1918   HandleScope scope;
1919
1920   int size = 0;
1921   while (environ[size]) size++;
1922
1923   Local<Array> env = Array::New(size);
1924
1925   for (int i = 0; i < size; ++i) {
1926     const char* var = environ[i];
1927     const char* s = strchr(var, '=');
1928     const int length = s ? s - var : strlen(var);
1929     env->Set(i, String::New(var, length));
1930   }
1931
1932   return scope.Close(env);
1933 }
1934
1935
1936 static void Load(int argc, char *argv[]) {
1937   HandleScope scope;
1938
1939   int i, j;
1940
1941   Local<FunctionTemplate> process_template = FunctionTemplate::New();
1942   node::EventEmitter::Initialize(process_template);
1943
1944   process = Persistent<Object>::New(process_template->GetFunction()->NewInstance());
1945
1946
1947   process->SetAccessor(String::New("title"),
1948                        ProcessTitleGetter,
1949                        ProcessTitleSetter);
1950
1951   // process.version
1952   process->Set(String::NewSymbol("version"), String::New(NODE_VERSION));
1953
1954   // process.installPrefix
1955   process->Set(String::NewSymbol("installPrefix"), String::New(NODE_PREFIX));
1956
1957   Local<Object> versions = Object::New();
1958   char buf[20];
1959   process->Set(String::NewSymbol("versions"), versions);
1960   // +1 to get rid of the leading 'v'
1961   versions->Set(String::NewSymbol("node"), String::New(NODE_VERSION+1));
1962   versions->Set(String::NewSymbol("v8"), String::New(V8::GetVersion()));
1963   versions->Set(String::NewSymbol("ares"), String::New(ARES_VERSION_STR));
1964   snprintf(buf, 20, "%d.%d", ev_version_major(), ev_version_minor());
1965   versions->Set(String::NewSymbol("ev"), String::New(buf));
1966 #ifdef HAVE_OPENSSL
1967   // Stupid code to slice out the version string.
1968   int c, l = strlen(OPENSSL_VERSION_TEXT);
1969   for (i = 0; i < l; i++) {
1970     c = OPENSSL_VERSION_TEXT[i];
1971     if ('0' <= c && c <= '9') {
1972       for (j = i + 1; j < l; j++) {
1973         c = OPENSSL_VERSION_TEXT[j];
1974         if (c == ' ') break;
1975       }
1976       break;
1977     }
1978   }
1979   versions->Set(String::NewSymbol("openssl"),
1980                 String::New(OPENSSL_VERSION_TEXT + i, j - i));
1981 #endif
1982
1983
1984
1985   // process.platform
1986   process->Set(String::NewSymbol("platform"), String::New(PLATFORM));
1987
1988   // process.argv
1989   Local<Array> arguments = Array::New(argc - option_end_index + 1);
1990   arguments->Set(Integer::New(0), String::New(argv[0]));
1991   for (j = 1, i = option_end_index; i < argc; j++, i++) {
1992     Local<String> arg = String::New(argv[i]);
1993     arguments->Set(Integer::New(j), arg);
1994   }
1995   // assign it
1996   process->Set(String::NewSymbol("ARGV"), arguments);
1997   process->Set(String::NewSymbol("argv"), arguments);
1998
1999   // create process.env
2000   Local<ObjectTemplate> envTemplate = ObjectTemplate::New();
2001   envTemplate->SetNamedPropertyHandler(EnvGetter,
2002                                        EnvSetter,
2003                                        EnvQuery,
2004                                        EnvDeleter,
2005                                        EnvEnumerator,
2006                                        Undefined());
2007   Local<Object> env = envTemplate->NewInstance();
2008   process->Set(String::NewSymbol("env"), env);
2009
2010   // create process.ENV
2011   // TODO: remove me at some point.
2012   Local<ObjectTemplate> ENVTemplate = ObjectTemplate::New();
2013   ENVTemplate->SetNamedPropertyHandler(EnvGetterWarn,
2014                                        EnvSetter,
2015                                        EnvQuery,
2016                                        EnvDeleter,
2017                                        EnvEnumerator,
2018                                        Undefined());
2019   Local<Object> ENV = ENVTemplate->NewInstance();
2020   process->Set(String::NewSymbol("ENV"), ENV);
2021
2022   process->Set(String::NewSymbol("pid"), Integer::New(getpid()));
2023
2024   // -e, --eval
2025   if (eval_string) {
2026     process->Set(String::NewSymbol("_eval"), String::New(eval_string));
2027   }
2028
2029   size_t size = 2*PATH_MAX;
2030   char execPath[size];
2031   if (Platform::GetExecutablePath(execPath, &size) != 0) {
2032     // as a last ditch effort, fallback on argv[0] ?
2033     process->Set(String::NewSymbol("execPath"), String::New(argv[0]));
2034   } else {
2035     process->Set(String::NewSymbol("execPath"), String::New(execPath, size));
2036   }
2037
2038
2039   // define various internal methods
2040   NODE_SET_METHOD(process, "compile", Compile);
2041   NODE_SET_METHOD(process, "_needTickCallback", NeedTickCallback);
2042   NODE_SET_METHOD(process, "reallyExit", Exit);
2043   NODE_SET_METHOD(process, "chdir", Chdir);
2044   NODE_SET_METHOD(process, "cwd", Cwd);
2045
2046 #ifdef __POSIX__
2047   NODE_SET_METHOD(process, "getuid", GetUid);
2048   NODE_SET_METHOD(process, "setuid", SetUid);
2049
2050   NODE_SET_METHOD(process, "setgid", SetGid);
2051   NODE_SET_METHOD(process, "getgid", GetGid);
2052
2053   NODE_SET_METHOD(process, "umask", Umask);
2054   NODE_SET_METHOD(process, "dlopen", DLOpen);
2055   NODE_SET_METHOD(process, "_kill", Kill);
2056 #endif // __POSIX__
2057
2058   NODE_SET_METHOD(process, "uptime", Uptime);
2059   NODE_SET_METHOD(process, "memoryUsage", MemoryUsage);
2060
2061   NODE_SET_METHOD(process, "binding", Binding);
2062
2063   // Assign the EventEmitter. It was created in main().
2064   process->Set(String::NewSymbol("EventEmitter"),
2065                EventEmitter::constructor_template->GetFunction());
2066
2067   // Compile, execute the src/node.js file. (Which was included as static C
2068   // string in node_natives.h. 'natve_node' is the string containing that
2069   // source code.)
2070
2071   // The node.js file returns a function 'f'
2072
2073   TryCatch try_catch;
2074
2075   Local<Value> f_value = ExecuteString(MainSource(),
2076                                        IMMUTABLE_STRING("node.js"));
2077   if (try_catch.HasCaught())  {
2078     ReportException(try_catch, true);
2079     exit(10);
2080   }
2081   assert(f_value->IsFunction());
2082   Local<Function> f = Local<Function>::Cast(f_value);
2083
2084   // Now we call 'f' with the 'process' variable that we've built up with
2085   // all our bindings. Inside node.js we'll take care of assigning things to
2086   // their places.
2087
2088   // We start the process this way in order to be more modular. Developers
2089   // who do not like how 'src/node.js' setups the module system but do like
2090   // Node's I/O bindings may want to replace 'f' with their own function.
2091
2092   // Add a reference to the global object
2093   Local<Object> global = v8::Context::GetCurrent()->Global();
2094   Local<Value> args[1] = { Local<Value>::New(process) };
2095
2096 #ifdef HAVE_DTRACE
2097   InitDTrace(global);
2098 #endif
2099
2100   f->Call(global, 1, args);
2101
2102   if (try_catch.HasCaught())  {
2103     ReportException(try_catch, true);
2104     exit(11);
2105   }
2106 }
2107
2108 static void PrintHelp();
2109
2110 static void ParseDebugOpt(const char* arg) {
2111   const char *p = 0;
2112
2113   use_debug_agent = true;
2114   if (!strcmp (arg, "--debug-brk")) {
2115     debug_wait_connect = true;
2116     return;
2117   } else if (!strcmp(arg, "--debug")) {
2118     return;
2119   } else if (strstr(arg, "--debug-brk=") == arg) {
2120     debug_wait_connect = true;
2121     p = 1 + strchr(arg, '=');
2122     debug_port = atoi(p);
2123   } else if (strstr(arg, "--debug=") == arg) {
2124     p = 1 + strchr(arg, '=');
2125     debug_port = atoi(p);
2126   }
2127   if (p && debug_port > 1024 && debug_port <  65536)
2128       return;
2129
2130   fprintf(stderr, "Bad debug option.\n");
2131   if (p) fprintf(stderr, "Debug port must be in range 1025 to 65535.\n");
2132
2133   PrintHelp();
2134   exit(1);
2135 }
2136
2137 static void PrintHelp() {
2138   printf("Usage: node [options] script.js [arguments] \n"
2139          "       node debug script.js [arguments] \n"
2140          "\n"
2141          "Options:\n"
2142          "  -v, --version        print node's version\n"
2143          "  --v8-options         print v8 command line options\n"
2144          "  --vars               print various compiled-in variables\n"
2145          "  --max-stack-size=val set max v8 stack size (bytes)\n"
2146          "\n"
2147          "Enviromental variables:\n"
2148          "NODE_PATH              ':'-separated list of directories\n"
2149          "                       prefixed to the module search path,\n"
2150          "                       require.paths.\n"
2151          "NODE_MODULE_CONTEXTS   Set to 1 to load modules in their own\n"
2152          "                       global contexts.\n"
2153          "NODE_DISABLE_COLORS    Set to 1 to disable colors in the REPL\n"
2154          "\n"
2155          "Documentation can be found at http://nodejs.org/\n");
2156 }
2157
2158 // Parse node command line arguments.
2159 static void ParseArgs(int *argc, char **argv) {
2160   int i;
2161
2162   // TODO use parse opts
2163   for (i = 1; i < *argc; i++) {
2164     const char *arg = argv[i];
2165     if (strstr(arg, "--debug") == arg) {
2166       ParseDebugOpt(arg);
2167       argv[i] = const_cast<char*>("");
2168     } else if (strcmp(arg, "--version") == 0 || strcmp(arg, "-v") == 0) {
2169       printf("%s\n", NODE_VERSION);
2170       exit(0);
2171     } else if (strcmp(arg, "--vars") == 0) {
2172       printf("NODE_PREFIX: %s\n", NODE_PREFIX);
2173       printf("NODE_CFLAGS: %s\n", NODE_CFLAGS);
2174       exit(0);
2175     } else if (strstr(arg, "--max-stack-size=") == arg) {
2176       const char *p = 0;
2177       p = 1 + strchr(arg, '=');
2178       max_stack_size = atoi(p);
2179       argv[i] = const_cast<char*>("");
2180     } else if (strcmp(arg, "--help") == 0 || strcmp(arg, "-h") == 0) {
2181       PrintHelp();
2182       exit(0);
2183     } else if (strcmp(arg, "--eval") == 0 || strcmp(arg, "-e") == 0) {
2184       if (*argc <= i + 1) {
2185         fprintf(stderr, "Error: --eval requires an argument\n");
2186         exit(1);
2187       }
2188       argv[i] = const_cast<char*>("");
2189       eval_string = argv[++i];
2190     } else if (strcmp(arg, "--v8-options") == 0) {
2191       argv[i] = const_cast<char*>("--help");
2192     } else if (argv[i][0] != '-') {
2193       break;
2194     }
2195   }
2196
2197   option_end_index = i;
2198 }
2199
2200
2201 static void AtExit() {
2202   node::Stdio::Flush();
2203   node::Stdio::DisableRawMode(STDIN_FILENO);
2204 }
2205
2206
2207 static void SignalExit(int signal) {
2208   Stdio::DisableRawMode(STDIN_FILENO);
2209   _exit(1);
2210 }
2211
2212
2213 static void EnableDebug(bool wait_connect) {
2214   // Start the debug thread and it's associated TCP server on port 5858.
2215   bool r = Debug::EnableAgent("node " NODE_VERSION, debug_port);
2216
2217   if (wait_connect) {
2218     // Set up an empty handler so v8 will not continue until a debugger
2219     // attaches. This is the same behavior as Debug::EnableAgent(_,_,true)
2220     // except we don't break at the beginning of the script.
2221     // see Debugger::StartAgent in debug.cc of v8/src
2222     Debug::SetMessageHandler2(node::DebugBreakMessageHandler);
2223   }
2224
2225   // Crappy check that everything went well. FIXME
2226   assert(r);
2227
2228   // Print out some information.
2229   fprintf(stderr, "debugger listening on port %d\r\n", debug_port);
2230 }
2231
2232
2233 static volatile bool hit_signal;
2234
2235
2236 static void EnableDebugSignalHandler(int signal) {
2237   // This is signal safe.
2238   hit_signal = true;
2239   v8::Debug::DebugBreak();
2240 }
2241
2242
2243 static void DebugSignalCB(const Debug::EventDetails& details) {
2244   if (hit_signal && details.GetEvent() == v8::Break) {
2245     hit_signal = false;
2246     fprintf(stderr, "Hit SIGUSR1 - starting debugger agent.\n");
2247     EnableDebug(false);
2248   }
2249 }
2250
2251
2252 #ifdef __POSIX__
2253
2254 static int RegisterSignalHandler(int signal, void (*handler)(int)) {
2255   struct sigaction sa;
2256
2257   memset(&sa, 0, sizeof(sa));
2258   sa.sa_handler = handler;
2259   sigfillset(&sa.sa_mask);
2260   return sigaction(signal, &sa, NULL);
2261 }
2262 #endif // __POSIX__
2263
2264
2265 int Start(int argc, char *argv[]) {
2266   // Hack aroung with the argv pointer. Used for process.title = "blah".
2267   argv = node::Platform::SetupArgs(argc, argv);
2268
2269   // Parse a few arguments which are specific to Node.
2270   node::ParseArgs(&argc, argv);
2271   // Parse the rest of the args (up to the 'option_end_index' (where '--' was
2272   // in the command line))
2273   int v8argc = node::option_end_index;
2274   char **v8argv = argv;
2275
2276   if (node::debug_wait_connect) {
2277     // v8argv is a copy of argv up to the script file argument +2 if --debug-brk
2278     // to expose the v8 debugger js object so that node.js can set
2279     // a breakpoint on the first line of the startup script
2280     v8argc += 2;
2281     v8argv = new char*[v8argc];
2282     memcpy(v8argv, argv, sizeof(argv) * node::option_end_index);
2283     v8argv[node::option_end_index] = const_cast<char*>("--expose_debug_as");
2284     v8argv[node::option_end_index + 1] = const_cast<char*>("v8debug");
2285   }
2286
2287   // For the normal stack which moves from high to low addresses when frames
2288   // are pushed, we can compute the limit as stack_size bytes below the
2289   // the address of a stack variable (e.g. &stack_var) as an approximation
2290   // of the start of the stack (we're assuming that we haven't pushed a lot
2291   // of frames yet).
2292   if (node::max_stack_size != 0) {
2293     uint32_t stack_var;
2294     ResourceConstraints constraints;
2295
2296     uint32_t *stack_limit = &stack_var - (node::max_stack_size / sizeof(uint32_t));
2297     constraints.set_stack_limit(stack_limit);
2298     SetResourceConstraints(&constraints); // Must be done before V8::Initialize
2299   }
2300   V8::SetFlagsFromCommandLine(&v8argc, v8argv, false);
2301
2302 #ifdef __POSIX__
2303   // Ignore SIGPIPE
2304   RegisterSignalHandler(SIGPIPE, SIG_IGN);
2305   RegisterSignalHandler(SIGINT, SignalExit);
2306   RegisterSignalHandler(SIGTERM, SignalExit);
2307 #endif // __POSIX__
2308
2309 #ifdef __MINGW32__
2310   // Initialize winsock and soem related caches
2311   wsa_init();
2312 #endif // __MINGW32__
2313
2314   // Initialize the default ev loop.
2315 #if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
2316   ev_default_loop(EVBACKEND_KQUEUE);
2317 #else
2318   ev_default_loop(EVFLAG_AUTO);
2319 #endif
2320
2321   ev_prepare_init(&node::prepare_tick_watcher, node::PrepareTick);
2322   ev_prepare_start(EV_DEFAULT_UC_ &node::prepare_tick_watcher);
2323   ev_unref(EV_DEFAULT_UC);
2324
2325   ev_check_init(&node::check_tick_watcher, node::CheckTick);
2326   ev_check_start(EV_DEFAULT_UC_ &node::check_tick_watcher);
2327   ev_unref(EV_DEFAULT_UC);
2328
2329   ev_idle_init(&node::tick_spinner, node::Spin);
2330
2331   ev_check_init(&node::gc_check, node::Check);
2332   ev_check_start(EV_DEFAULT_UC_ &node::gc_check);
2333   ev_unref(EV_DEFAULT_UC);
2334
2335   ev_idle_init(&node::gc_idle, node::Idle);
2336   ev_timer_init(&node::gc_timer, node::CheckStatus, 5., 5.);
2337
2338
2339   // Setup the EIO thread pool
2340   { // It requires 3, yes 3, watchers.
2341     ev_idle_init(&node::eio_poller, node::DoPoll);
2342
2343     ev_async_init(&node::eio_want_poll_notifier, node::WantPollNotifier);
2344     ev_async_start(EV_DEFAULT_UC_ &node::eio_want_poll_notifier);
2345     ev_unref(EV_DEFAULT_UC);
2346
2347     ev_async_init(&node::eio_done_poll_notifier, node::DonePollNotifier);
2348     ev_async_start(EV_DEFAULT_UC_ &node::eio_done_poll_notifier);
2349     ev_unref(EV_DEFAULT_UC);
2350
2351     eio_init(node::EIOWantPoll, node::EIODonePoll);
2352     // Don't handle more than 10 reqs on each eio_poll(). This is to avoid
2353     // race conditions. See test/simple/test-eio-race.js
2354     eio_set_max_poll_reqs(10);
2355   }
2356
2357   V8::Initialize();
2358   HandleScope handle_scope;
2359
2360   V8::SetFatalErrorHandler(node::OnFatalError);
2361
2362
2363   // Initialize the async watcher for receiving messages from the debug
2364   // thread and marshal it into the main thread. DebugMessageCallback()
2365   // is called from the main thread to execute a random bit of javascript
2366   // - which will give V8 control so it can handle whatever new message
2367   // had been received on the debug thread.
2368   ev_async_init(&node::debug_watcher, node::DebugMessageCallback);
2369   ev_set_priority(&node::debug_watcher, EV_MAXPRI);
2370   // Set the callback DebugMessageDispatch which is called from the debug
2371   // thread.
2372   Debug::SetDebugMessageDispatchHandler(node::DebugMessageDispatch);
2373   // Start the async watcher.
2374   ev_async_start(EV_DEFAULT_UC_ &node::debug_watcher);
2375   // unref it so that we exit the event loop despite it being active.
2376   ev_unref(EV_DEFAULT_UC);
2377
2378
2379   // If the --debug flag was specified then initialize the debug thread.
2380   if (node::use_debug_agent) {
2381     EnableDebug(debug_wait_connect);
2382   } else {
2383 #ifdef __POSIX__
2384     RegisterSignalHandler(SIGUSR1, EnableDebugSignalHandler);
2385     Debug::SetDebugEventListener2(DebugSignalCB);
2386 #endif // __POSIX__
2387   }
2388
2389   // Create the one and only Context.
2390   Persistent<v8::Context> context = v8::Context::New();
2391   v8::Context::Scope context_scope(context);
2392
2393   atexit(node::AtExit);
2394
2395   // Create all the objects, load modules, do everything.
2396   // so your next reading stop should be node::Load()!
2397   node::Load(argc, argv);
2398
2399   // TODO Probably don't need to start this each time.
2400   // Avoids failing on test/simple/test-eio-race3.js though
2401   ev_idle_start(EV_DEFAULT_UC_ &eio_poller);
2402
2403   // All our arguments are loaded. We've evaluated all of the scripts. We
2404   // might even have created TCP servers. Now we enter the main eventloop. If
2405   // there are no watchers on the loop (except for the ones that were
2406   // ev_unref'd) then this function exits. As long as there are active
2407   // watchers, it blocks.
2408   ev_loop(EV_DEFAULT_UC_ 0);
2409
2410
2411   // process.emit('exit')
2412   Local<Value> emit_v = process->Get(String::New("emit"));
2413   assert(emit_v->IsFunction());
2414   Local<Function> emit = Local<Function>::Cast(emit_v);
2415   Local<Value> args[] = { String::New("exit") };
2416   TryCatch try_catch;
2417   emit->Call(process, 1, args);
2418   if (try_catch.HasCaught()) {
2419     FatalException(try_catch);
2420   }
2421
2422
2423 #ifndef NDEBUG
2424   // Clean up.
2425   context.Dispose();
2426   V8::Dispose();
2427 #endif  // NDEBUG
2428   return 0;
2429 }
2430
2431
2432 }  // namespace node