The data contained in this repository can be downloaded to your computer using one of several clients.
Please see the documentation of your version control software client for more information.

Please select the desired protocol below to get the URL.

This URL has Read-Only access.

Statistics
| Branch: | Revision:

main_repo / src / node.cc @ 35a1421e

History | View | Annotate | Download (72 KB)

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
#include "req_wrap.h"
24
#include "handle_wrap.h"
25

    
26
#include "uv.h"
27

    
28
#include "v8-debug.h"
29
#if defined HAVE_DTRACE || defined HAVE_ETW
30
# include "node_dtrace.h"
31
#endif
32

    
33
#ifdef HAVE_ETW
34
# include "node_win32_etw_provider.h"
35
#endif
36

    
37
#include <locale.h>
38
#include <signal.h>
39
#include <stdio.h>
40
#include <stdlib.h>
41
#include <string.h>
42
#if !defined(_MSC_VER)
43
#include <strings.h>
44
#else
45
#define strcasecmp _stricmp
46
#endif
47
#include <limits.h> /* PATH_MAX */
48
#include <assert.h>
49
#if !defined(_MSC_VER)
50
#include <unistd.h> /* setuid, getuid */
51
#else
52
#include <direct.h>
53
#include <process.h>
54
#define getpid _getpid
55
#include <io.h>
56
#define umask _umask
57
typedef int mode_t;
58
#endif
59
#include <errno.h>
60
#include <sys/types.h>
61
#include "zlib.h"
62

    
63
#ifdef __POSIX__
64
# include <pwd.h> /* getpwnam() */
65
# include <grp.h> /* getgrnam() */
66
#endif
67

    
68
#include "node_buffer.h"
69
#ifdef __POSIX__
70
# include "node_io_watcher.h"
71
#endif
72
#include "node_file.h"
73
#include "node_http_parser.h"
74
#ifdef __POSIX__
75
# include "node_signal_watcher.h"
76
# include "node_stat_watcher.h"
77
#endif
78
#include "node_constants.h"
79
#include "node_javascript.h"
80
#include "node_version.h"
81
#include "node_string.h"
82
#if HAVE_OPENSSL
83
# include "node_crypto.h"
84
#endif
85
#include "node_script.h"
86
#include "v8_typed_array.h"
87

    
88
using namespace v8;
89

    
90
# ifdef __APPLE__
91
# include <crt_externs.h>
92
# define environ (*_NSGetEnviron())
93
# elif !defined(_MSC_VER)
94
extern char **environ;
95
# endif
96

    
97
namespace node {
98

    
99
ngx_queue_t handle_wrap_queue = { &handle_wrap_queue, &handle_wrap_queue };
100
ngx_queue_t req_wrap_queue = { &req_wrap_queue, &req_wrap_queue };
101

    
102
// declared in req_wrap.h
103
Persistent<String> process_symbol;
104
Persistent<String> domain_symbol;
105

    
106
static Persistent<Object> process;
107

    
108
static Persistent<String> errno_symbol;
109
static Persistent<String> syscall_symbol;
110
static Persistent<String> errpath_symbol;
111
static Persistent<String> code_symbol;
112

    
113
static Persistent<String> rss_symbol;
114
static Persistent<String> heap_total_symbol;
115
static Persistent<String> heap_used_symbol;
116

    
117
static Persistent<String> listeners_symbol;
118
static Persistent<String> uncaught_exception_symbol;
119
static Persistent<String> emit_symbol;
120

    
121
static Persistent<String> enter_symbol;
122
static Persistent<String> exit_symbol;
123
static Persistent<String> disposed_symbol;
124

    
125

    
126
static bool print_eval = false;
127
static bool force_repl = false;
128
static char *eval_string = NULL;
129
static int option_end_index = 0;
130
static bool use_debug_agent = false;
131
static bool debug_wait_connect = false;
132
static int debug_port=5858;
133
static int max_stack_size = 0;
134

    
135
static uv_check_t check_tick_watcher;
136
static uv_prepare_t prepare_tick_watcher;
137
static uv_idle_t tick_spinner;
138
static bool need_tick_cb;
139
static Persistent<String> tick_callback_sym;
140

    
141

    
142
#ifdef OPENSSL_NPN_NEGOTIATED
143
static bool use_npn = true;
144
#else
145
static bool use_npn = false;
146
#endif
147

    
148
#ifdef SSL_CTRL_SET_TLSEXT_SERVERNAME_CB
149
static bool use_sni = true;
150
#else
151
static bool use_sni = false;
152
#endif
153

    
154
#ifdef __POSIX__
155
// Buffer for getpwnam_r(), getgrpam_r() and other misc callers; keep this
156
// scoped at file-level rather than method-level to avoid excess stack usage.
157
static char getbuf[PATH_MAX + 1];
158
#endif
159

    
160
// We need to notify V8 when we're idle so that it can run the garbage
161
// collector. The interface to this is V8::IdleNotification(). It returns
162
// true if the heap hasn't be fully compacted, and needs to be run again.
163
// Returning false means that it doesn't have anymore work to do.
164
//
165
// A rather convoluted algorithm has been devised to determine when Node is
166
// idle. You'll have to figure it out for yourself.
167
static uv_check_t gc_check;
168
static uv_idle_t gc_idle;
169
static uv_timer_t gc_timer;
170
bool need_gc;
171

    
172
// process-relative uptime base, initialized at start-up
173
static double prog_start_time;
174

    
175
#define FAST_TICK 700.
176
#define GC_WAIT_TIME 5000.
177
#define RPM_SAMPLES 100
178
#define TICK_TIME(n) tick_times[(tick_time_head - (n)) % RPM_SAMPLES]
179
static int64_t tick_times[RPM_SAMPLES];
180
static int tick_time_head;
181

    
182
static void CheckStatus(uv_timer_t* watcher, int status);
183

    
184
static void StartGCTimer () {
185
  if (!uv_is_active((uv_handle_t*) &gc_timer)) {
186
    uv_timer_start(&gc_timer, node::CheckStatus, 5000, 5000);
187
  }
188
}
189

    
190
static void StopGCTimer () {
191
  if (uv_is_active((uv_handle_t*) &gc_timer)) {
192
    uv_timer_stop(&gc_timer);
193
  }
194
}
195

    
196
static void Idle(uv_idle_t* watcher, int status) {
197
  assert((uv_idle_t*) watcher == &gc_idle);
198

    
199
  if (V8::IdleNotification()) {
200
    uv_idle_stop(&gc_idle);
201
    StopGCTimer();
202
  }
203
}
204

    
205

    
206
// Called directly after every call to select() (or epoll, or whatever)
207
static void Check(uv_check_t* watcher, int status) {
208
  assert(watcher == &gc_check);
209

    
210
  tick_times[tick_time_head] = uv_now(uv_default_loop());
211
  tick_time_head = (tick_time_head + 1) % RPM_SAMPLES;
212

    
213
  StartGCTimer();
214

    
215
  for (int i = 0; i < (int)(GC_WAIT_TIME/FAST_TICK); i++) {
216
    double d = TICK_TIME(i+1) - TICK_TIME(i+2);
217
    //printf("d = %f\n", d);
218
    // If in the last 5 ticks the difference between
219
    // ticks was less than 0.7 seconds, then continue.
220
    if (d < FAST_TICK) {
221
      //printf("---\n");
222
      return;
223
    }
224
  }
225

    
226
  // Otherwise start the gc!
227

    
228
  //fprintf(stderr, "start idle 2\n");
229
  uv_idle_start(&gc_idle, node::Idle);
230
}
231

    
232

    
233
static void Tick(void) {
234
  // Avoid entering a V8 scope.
235
  if (!need_tick_cb) return;
236
  need_tick_cb = false;
237

    
238
  uv_idle_stop(&tick_spinner);
239

    
240
  HandleScope scope;
241

    
242
  if (tick_callback_sym.IsEmpty()) {
243
    // Lazily set the symbol
244
    tick_callback_sym = NODE_PSYMBOL("_tickCallback");
245
  }
246

    
247
  Local<Value> cb_v = process->Get(tick_callback_sym);
248
  if (!cb_v->IsFunction()) return;
249
  Local<Function> cb = Local<Function>::Cast(cb_v);
250

    
251
  TryCatch try_catch;
252

    
253
  cb->Call(process, 0, NULL);
254

    
255
  if (try_catch.HasCaught()) {
256
    FatalException(try_catch);
257
  }
258
}
259

    
260

    
261
static void Spin(uv_idle_t* handle, int status) {
262
  assert((uv_idle_t*) handle == &tick_spinner);
263
  assert(status == 0);
264
  Tick();
265
}
266

    
267
static void StartTickSpinner() {
268
  need_tick_cb = true;
269
  // TODO: this tick_spinner shouldn't be necessary. An ev_prepare should be
270
  // sufficent, the problem is only in the case of the very last "tick" -
271
  // there is nothing left to do in the event loop and libev will exit. The
272
  // ev_prepare callback isn't called before exiting. Thus we start this
273
  // tick_spinner to keep the event loop alive long enough to handle it.
274
  uv_idle_start(&tick_spinner, Spin);
275
}
276

    
277
static Handle<Value> NeedTickCallback(const Arguments& args) {
278
  StartTickSpinner();
279
  return Undefined();
280
}
281

    
282
static void PrepareTick(uv_prepare_t* handle, int status) {
283
  assert(handle == &prepare_tick_watcher);
284
  assert(status == 0);
285
  Tick();
286
}
287

    
288

    
289
static void CheckTick(uv_check_t* handle, int status) {
290
  assert(handle == &check_tick_watcher);
291
  assert(status == 0);
292
  Tick();
293
}
294

    
295
static inline const char *errno_string(int errorno) {
296
#define ERRNO_CASE(e)  case e: return #e;
297
  switch (errorno) {
298

    
299
#ifdef EACCES
300
  ERRNO_CASE(EACCES);
301
#endif
302

    
303
#ifdef EADDRINUSE
304
  ERRNO_CASE(EADDRINUSE);
305
#endif
306

    
307
#ifdef EADDRNOTAVAIL
308
  ERRNO_CASE(EADDRNOTAVAIL);
309
#endif
310

    
311
#ifdef EAFNOSUPPORT
312
  ERRNO_CASE(EAFNOSUPPORT);
313
#endif
314

    
315
#ifdef EAGAIN
316
  ERRNO_CASE(EAGAIN);
317
#endif
318

    
319
#ifdef EWOULDBLOCK
320
# if EAGAIN != EWOULDBLOCK
321
  ERRNO_CASE(EWOULDBLOCK);
322
# endif
323
#endif
324

    
325
#ifdef EALREADY
326
  ERRNO_CASE(EALREADY);
327
#endif
328

    
329
#ifdef EBADF
330
  ERRNO_CASE(EBADF);
331
#endif
332

    
333
#ifdef EBADMSG
334
  ERRNO_CASE(EBADMSG);
335
#endif
336

    
337
#ifdef EBUSY
338
  ERRNO_CASE(EBUSY);
339
#endif
340

    
341
#ifdef ECANCELED
342
  ERRNO_CASE(ECANCELED);
343
#endif
344

    
345
#ifdef ECHILD
346
  ERRNO_CASE(ECHILD);
347
#endif
348

    
349
#ifdef ECONNABORTED
350
  ERRNO_CASE(ECONNABORTED);
351
#endif
352

    
353
#ifdef ECONNREFUSED
354
  ERRNO_CASE(ECONNREFUSED);
355
#endif
356

    
357
#ifdef ECONNRESET
358
  ERRNO_CASE(ECONNRESET);
359
#endif
360

    
361
#ifdef EDEADLK
362
  ERRNO_CASE(EDEADLK);
363
#endif
364

    
365
#ifdef EDESTADDRREQ
366
  ERRNO_CASE(EDESTADDRREQ);
367
#endif
368

    
369
#ifdef EDOM
370
  ERRNO_CASE(EDOM);
371
#endif
372

    
373
#ifdef EDQUOT
374
  ERRNO_CASE(EDQUOT);
375
#endif
376

    
377
#ifdef EEXIST
378
  ERRNO_CASE(EEXIST);
379
#endif
380

    
381
#ifdef EFAULT
382
  ERRNO_CASE(EFAULT);
383
#endif
384

    
385
#ifdef EFBIG
386
  ERRNO_CASE(EFBIG);
387
#endif
388

    
389
#ifdef EHOSTUNREACH
390
  ERRNO_CASE(EHOSTUNREACH);
391
#endif
392

    
393
#ifdef EIDRM
394
  ERRNO_CASE(EIDRM);
395
#endif
396

    
397
#ifdef EILSEQ
398
  ERRNO_CASE(EILSEQ);
399
#endif
400

    
401
#ifdef EINPROGRESS
402
  ERRNO_CASE(EINPROGRESS);
403
#endif
404

    
405
#ifdef EINTR
406
  ERRNO_CASE(EINTR);
407
#endif
408

    
409
#ifdef EINVAL
410
  ERRNO_CASE(EINVAL);
411
#endif
412

    
413
#ifdef EIO
414
  ERRNO_CASE(EIO);
415
#endif
416

    
417
#ifdef EISCONN
418
  ERRNO_CASE(EISCONN);
419
#endif
420

    
421
#ifdef EISDIR
422
  ERRNO_CASE(EISDIR);
423
#endif
424

    
425
#ifdef ELOOP
426
  ERRNO_CASE(ELOOP);
427
#endif
428

    
429
#ifdef EMFILE
430
  ERRNO_CASE(EMFILE);
431
#endif
432

    
433
#ifdef EMLINK
434
  ERRNO_CASE(EMLINK);
435
#endif
436

    
437
#ifdef EMSGSIZE
438
  ERRNO_CASE(EMSGSIZE);
439
#endif
440

    
441
#ifdef EMULTIHOP
442
  ERRNO_CASE(EMULTIHOP);
443
#endif
444

    
445
#ifdef ENAMETOOLONG
446
  ERRNO_CASE(ENAMETOOLONG);
447
#endif
448

    
449
#ifdef ENETDOWN
450
  ERRNO_CASE(ENETDOWN);
451
#endif
452

    
453
#ifdef ENETRESET
454
  ERRNO_CASE(ENETRESET);
455
#endif
456

    
457
#ifdef ENETUNREACH
458
  ERRNO_CASE(ENETUNREACH);
459
#endif
460

    
461
#ifdef ENFILE
462
  ERRNO_CASE(ENFILE);
463
#endif
464

    
465
#ifdef ENOBUFS
466
  ERRNO_CASE(ENOBUFS);
467
#endif
468

    
469
#ifdef ENODATA
470
  ERRNO_CASE(ENODATA);
471
#endif
472

    
473
#ifdef ENODEV
474
  ERRNO_CASE(ENODEV);
475
#endif
476

    
477
#ifdef ENOENT
478
  ERRNO_CASE(ENOENT);
479
#endif
480

    
481
#ifdef ENOEXEC
482
  ERRNO_CASE(ENOEXEC);
483
#endif
484

    
485
#ifdef ENOLINK
486
  ERRNO_CASE(ENOLINK);
487
#endif
488

    
489
#ifdef ENOLCK
490
# if ENOLINK != ENOLCK
491
  ERRNO_CASE(ENOLCK);
492
# endif
493
#endif
494

    
495
#ifdef ENOMEM
496
  ERRNO_CASE(ENOMEM);
497
#endif
498

    
499
#ifdef ENOMSG
500
  ERRNO_CASE(ENOMSG);
501
#endif
502

    
503
#ifdef ENOPROTOOPT
504
  ERRNO_CASE(ENOPROTOOPT);
505
#endif
506

    
507
#ifdef ENOSPC
508
  ERRNO_CASE(ENOSPC);
509
#endif
510

    
511
#ifdef ENOSR
512
  ERRNO_CASE(ENOSR);
513
#endif
514

    
515
#ifdef ENOSTR
516
  ERRNO_CASE(ENOSTR);
517
#endif
518

    
519
#ifdef ENOSYS
520
  ERRNO_CASE(ENOSYS);
521
#endif
522

    
523
#ifdef ENOTCONN
524
  ERRNO_CASE(ENOTCONN);
525
#endif
526

    
527
#ifdef ENOTDIR
528
  ERRNO_CASE(ENOTDIR);
529
#endif
530

    
531
#ifdef ENOTEMPTY
532
  ERRNO_CASE(ENOTEMPTY);
533
#endif
534

    
535
#ifdef ENOTSOCK
536
  ERRNO_CASE(ENOTSOCK);
537
#endif
538

    
539
#ifdef ENOTSUP
540
  ERRNO_CASE(ENOTSUP);
541
#else
542
# ifdef EOPNOTSUPP
543
  ERRNO_CASE(EOPNOTSUPP);
544
# endif
545
#endif
546

    
547
#ifdef ENOTTY
548
  ERRNO_CASE(ENOTTY);
549
#endif
550

    
551
#ifdef ENXIO
552
  ERRNO_CASE(ENXIO);
553
#endif
554

    
555

    
556
#ifdef EOVERFLOW
557
  ERRNO_CASE(EOVERFLOW);
558
#endif
559

    
560
#ifdef EPERM
561
  ERRNO_CASE(EPERM);
562
#endif
563

    
564
#ifdef EPIPE
565
  ERRNO_CASE(EPIPE);
566
#endif
567

    
568
#ifdef EPROTO
569
  ERRNO_CASE(EPROTO);
570
#endif
571

    
572
#ifdef EPROTONOSUPPORT
573
  ERRNO_CASE(EPROTONOSUPPORT);
574
#endif
575

    
576
#ifdef EPROTOTYPE
577
  ERRNO_CASE(EPROTOTYPE);
578
#endif
579

    
580
#ifdef ERANGE
581
  ERRNO_CASE(ERANGE);
582
#endif
583

    
584
#ifdef EROFS
585
  ERRNO_CASE(EROFS);
586
#endif
587

    
588
#ifdef ESPIPE
589
  ERRNO_CASE(ESPIPE);
590
#endif
591

    
592
#ifdef ESRCH
593
  ERRNO_CASE(ESRCH);
594
#endif
595

    
596
#ifdef ESTALE
597
  ERRNO_CASE(ESTALE);
598
#endif
599

    
600
#ifdef ETIME
601
  ERRNO_CASE(ETIME);
602
#endif
603

    
604
#ifdef ETIMEDOUT
605
  ERRNO_CASE(ETIMEDOUT);
606
#endif
607

    
608
#ifdef ETXTBSY
609
  ERRNO_CASE(ETXTBSY);
610
#endif
611

    
612
#ifdef EXDEV
613
  ERRNO_CASE(EXDEV);
614
#endif
615

    
616
  default: return "";
617
  }
618
}
619

    
620
const char *signo_string(int signo) {
621
#define SIGNO_CASE(e)  case e: return #e;
622
  switch (signo) {
623

    
624
#ifdef SIGHUP
625
  SIGNO_CASE(SIGHUP);
626
#endif
627

    
628
#ifdef SIGINT
629
  SIGNO_CASE(SIGINT);
630
#endif
631

    
632
#ifdef SIGQUIT
633
  SIGNO_CASE(SIGQUIT);
634
#endif
635

    
636
#ifdef SIGILL
637
  SIGNO_CASE(SIGILL);
638
#endif
639

    
640
#ifdef SIGTRAP
641
  SIGNO_CASE(SIGTRAP);
642
#endif
643

    
644
#ifdef SIGABRT
645
  SIGNO_CASE(SIGABRT);
646
#endif
647

    
648
#ifdef SIGIOT
649
# if SIGABRT != SIGIOT
650
  SIGNO_CASE(SIGIOT);
651
# endif
652
#endif
653

    
654
#ifdef SIGBUS
655
  SIGNO_CASE(SIGBUS);
656
#endif
657

    
658
#ifdef SIGFPE
659
  SIGNO_CASE(SIGFPE);
660
#endif
661

    
662
#ifdef SIGKILL
663
  SIGNO_CASE(SIGKILL);
664
#endif
665

    
666
#ifdef SIGUSR1
667
  SIGNO_CASE(SIGUSR1);
668
#endif
669

    
670
#ifdef SIGSEGV
671
  SIGNO_CASE(SIGSEGV);
672
#endif
673

    
674
#ifdef SIGUSR2
675
  SIGNO_CASE(SIGUSR2);
676
#endif
677

    
678
#ifdef SIGPIPE
679
  SIGNO_CASE(SIGPIPE);
680
#endif
681

    
682
#ifdef SIGALRM
683
  SIGNO_CASE(SIGALRM);
684
#endif
685

    
686
  SIGNO_CASE(SIGTERM);
687

    
688
#ifdef SIGCHLD
689
  SIGNO_CASE(SIGCHLD);
690
#endif
691

    
692
#ifdef SIGSTKFLT
693
  SIGNO_CASE(SIGSTKFLT);
694
#endif
695

    
696

    
697
#ifdef SIGCONT
698
  SIGNO_CASE(SIGCONT);
699
#endif
700

    
701
#ifdef SIGSTOP
702
  SIGNO_CASE(SIGSTOP);
703
#endif
704

    
705
#ifdef SIGTSTP
706
  SIGNO_CASE(SIGTSTP);
707
#endif
708

    
709
#ifdef SIGTTIN
710
  SIGNO_CASE(SIGTTIN);
711
#endif
712

    
713
#ifdef SIGTTOU
714
  SIGNO_CASE(SIGTTOU);
715
#endif
716

    
717
#ifdef SIGURG
718
  SIGNO_CASE(SIGURG);
719
#endif
720

    
721
#ifdef SIGXCPU
722
  SIGNO_CASE(SIGXCPU);
723
#endif
724

    
725
#ifdef SIGXFSZ
726
  SIGNO_CASE(SIGXFSZ);
727
#endif
728

    
729
#ifdef SIGVTALRM
730
  SIGNO_CASE(SIGVTALRM);
731
#endif
732

    
733
#ifdef SIGPROF
734
  SIGNO_CASE(SIGPROF);
735
#endif
736

    
737
#ifdef SIGWINCH
738
  SIGNO_CASE(SIGWINCH);
739
#endif
740

    
741
#ifdef SIGIO
742
  SIGNO_CASE(SIGIO);
743
#endif
744

    
745
#ifdef SIGPOLL
746
# if SIGPOLL != SIGIO
747
  SIGNO_CASE(SIGPOLL);
748
# endif
749
#endif
750

    
751
#ifdef SIGLOST
752
  SIGNO_CASE(SIGLOST);
753
#endif
754

    
755
#ifdef SIGPWR
756
# if SIGPWR != SIGLOST
757
  SIGNO_CASE(SIGPWR);
758
# endif
759
#endif
760

    
761
#ifdef SIGSYS
762
  SIGNO_CASE(SIGSYS);
763
#endif
764

    
765
  default: return "";
766
  }
767
}
768

    
769

    
770
Local<Value> ErrnoException(int errorno,
771
                            const char *syscall,
772
                            const char *msg,
773
                            const char *path) {
774
  Local<Value> e;
775
  Local<String> estring = String::NewSymbol(errno_string(errorno));
776
  if (!msg[0]) {
777
    msg = strerror(errorno);
778
  }
779
  Local<String> message = String::NewSymbol(msg);
780

    
781
  Local<String> cons1 = String::Concat(estring, String::NewSymbol(", "));
782
  Local<String> cons2 = String::Concat(cons1, message);
783

    
784
  if (syscall_symbol.IsEmpty()) {
785
    syscall_symbol = NODE_PSYMBOL("syscall");
786
    errno_symbol = NODE_PSYMBOL("errno");
787
    errpath_symbol = NODE_PSYMBOL("path");
788
    code_symbol = NODE_PSYMBOL("code");
789
  }
790

    
791
  if (path) {
792
    Local<String> cons3 = String::Concat(cons2, String::NewSymbol(" '"));
793
    Local<String> cons4 = String::Concat(cons3, String::New(path));
794
    Local<String> cons5 = String::Concat(cons4, String::NewSymbol("'"));
795
    e = Exception::Error(cons5);
796
  } else {
797
    e = Exception::Error(cons2);
798
  }
799

    
800
  Local<Object> obj = e->ToObject();
801

    
802
  obj->Set(errno_symbol, Integer::New(errorno));
803
  obj->Set(code_symbol, estring);
804
  if (path) obj->Set(errpath_symbol, String::New(path));
805
  if (syscall) obj->Set(syscall_symbol, String::NewSymbol(syscall));
806
  return e;
807
}
808

    
809

    
810
static const char* get_uv_errno_string(int errorno) {
811
  uv_err_t err;
812
  memset(&err, 0, sizeof err);
813
  err.code = (uv_err_code)errorno;
814
  return uv_err_name(err);
815
}
816

    
817

    
818
static const char* get_uv_errno_message(int errorno) {
819
  uv_err_t err;
820
  memset(&err, 0, sizeof err);
821
  err.code = (uv_err_code)errorno;
822
  return uv_strerror(err);
823
}
824

    
825

    
826
// hack alert! copy of ErrnoException, tuned for uv errors
827
Local<Value> UVException(int errorno,
828
                         const char *syscall,
829
                         const char *msg,
830
                         const char *path) {
831
  if (syscall_symbol.IsEmpty()) {
832
    syscall_symbol = NODE_PSYMBOL("syscall");
833
    errno_symbol = NODE_PSYMBOL("errno");
834
    errpath_symbol = NODE_PSYMBOL("path");
835
    code_symbol = NODE_PSYMBOL("code");
836
  }
837

    
838
  if (!msg || !msg[0])
839
    msg = get_uv_errno_message(errorno);
840

    
841
  Local<String> estring = String::NewSymbol(get_uv_errno_string(errorno));
842
  Local<String> message = String::NewSymbol(msg);
843
  Local<String> cons1 = String::Concat(estring, String::NewSymbol(", "));
844
  Local<String> cons2 = String::Concat(cons1, message);
845

    
846
  Local<Value> e;
847

    
848
  Local<String> path_str;
849

    
850
  if (path) {
851
#ifdef _WIN32
852
    if (strncmp(path, "\\\\?\\UNC\\", 8) == 0) {
853
      path_str = String::Concat(String::New("\\\\"), String::New(path + 8));
854
    } else if (strncmp(path, "\\\\?\\", 4) == 0) {
855
      path_str = String::New(path + 4);
856
    } else {
857
      path_str = String::New(path);
858
    }
859
#else
860
    path_str = String::New(path);
861
#endif
862

    
863
    Local<String> cons3 = String::Concat(cons2, String::NewSymbol(" '"));
864
    Local<String> cons4 = String::Concat(cons3, path_str);
865
    Local<String> cons5 = String::Concat(cons4, String::NewSymbol("'"));
866
    e = Exception::Error(cons5);
867
  } else {
868
    e = Exception::Error(cons2);
869
  }
870

    
871
  Local<Object> obj = e->ToObject();
872

    
873
  // TODO errno should probably go
874
  obj->Set(errno_symbol, Integer::New(errorno));
875
  obj->Set(code_symbol, estring);
876
  if (path) obj->Set(errpath_symbol, path_str);
877
  if (syscall) obj->Set(syscall_symbol, String::NewSymbol(syscall));
878
  return e;
879
}
880

    
881

    
882
#ifdef _WIN32
883
// Does about the same as strerror(),
884
// but supports all windows error messages
885
static const char *winapi_strerror(const int errorno) {
886
  char *errmsg = NULL;
887

    
888
  FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
889
      FORMAT_MESSAGE_IGNORE_INSERTS, NULL, errorno,
890
      MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&errmsg, 0, NULL);
891

    
892
  if (errmsg) {
893
    // Remove trailing newlines
894
    for (int i = strlen(errmsg) - 1;
895
        i >= 0 && (errmsg[i] == '\n' || errmsg[i] == '\r'); i--) {
896
      errmsg[i] = '\0';
897
    }
898

    
899
    return errmsg;
900
  } else {
901
    // FormatMessage failed
902
    return "Unknown error";
903
  }
904
}
905

    
906

    
907
Local<Value> WinapiErrnoException(int errorno,
908
                                  const char* syscall,
909
                                  const char* msg,
910
                                  const char* path) {
911
  Local<Value> e;
912
  if (!msg || !msg[0]) {
913
    msg = winapi_strerror(errorno);
914
  }
915
  Local<String> message = String::NewSymbol(msg);
916

    
917
  if (syscall_symbol.IsEmpty()) {
918
    syscall_symbol = NODE_PSYMBOL("syscall");
919
    errno_symbol = NODE_PSYMBOL("errno");
920
    errpath_symbol = NODE_PSYMBOL("path");
921
    code_symbol = NODE_PSYMBOL("code");
922
  }
923

    
924
  if (path) {
925
    Local<String> cons1 = String::Concat(message, String::NewSymbol(" '"));
926
    Local<String> cons2 = String::Concat(cons1, String::New(path));
927
    Local<String> cons3 = String::Concat(cons2, String::NewSymbol("'"));
928
    e = Exception::Error(cons3);
929
  } else {
930
    e = Exception::Error(message);
931
  }
932

    
933
  Local<Object> obj = e->ToObject();
934

    
935
  obj->Set(errno_symbol, Integer::New(errorno));
936
  if (path) obj->Set(errpath_symbol, String::New(path));
937
  if (syscall) obj->Set(syscall_symbol, String::NewSymbol(syscall));
938
  return e;
939
}
940
#endif
941

    
942

    
943
Handle<Value> FromConstructorTemplate(Persistent<FunctionTemplate>& t,
944
                                      const Arguments& args) {
945
  HandleScope scope;
946

    
947
  const int argc = args.Length();
948
  Local<Value>* argv = new Local<Value>[argc];
949

    
950
  for (int i = 0; i < argc; ++i) {
951
    argv[i] = args[i];
952
  }
953

    
954
  Local<Object> instance = t->GetFunction()->NewInstance(argc, argv);
955

    
956
  delete[] argv;
957

    
958
  return scope.Close(instance);
959
}
960

    
961

    
962
// MakeCallback may only be made directly off the event loop.
963
// That is there can be no JavaScript stack frames underneath it.
964
// (Is there any way to assert that?)
965
//
966
// Maybe make this a method of a node::Handle super class
967
//
968
Handle<Value>
969
MakeCallback(const Handle<Object> object,
970
             const char* method,
971
             int argc,
972
             Handle<Value> argv[]) {
973
  HandleScope scope;
974

    
975
  Handle<Value> ret =
976
    MakeCallback(object, String::NewSymbol(method), argc, argv);
977

    
978
  return scope.Close(ret);
979
}
980

    
981
Handle<Value>
982
MakeCallback(const Handle<Object> object,
983
             const Handle<String> symbol,
984
             int argc,
985
             Handle<Value> argv[]) {
986
  HandleScope scope;
987

    
988
  Local<Value> callback_v = object->Get(symbol);
989
  if (!callback_v->IsFunction()) {
990
    String::Utf8Value method(symbol);
991
    // XXX: If the object has a domain attached, handle it there?
992
    // At least, would be good to get *some* sort of indication
993
    // of how we got here, even if it's not catchable.
994
    fprintf(stderr, "Non-function in MakeCallback. method = %s\n", *method);
995
    abort();
996
  }
997

    
998
  Local<Function> callback = Local<Function>::Cast(callback_v);
999

    
1000
  return scope.Close(MakeCallback(object, callback, argc, argv));
1001
}
1002

    
1003
Handle<Value>
1004
MakeCallback(const Handle<Object> object,
1005
             const Handle<Function> callback,
1006
             int argc,
1007
             Handle<Value> argv[]) {
1008
  HandleScope scope;
1009

    
1010
  // TODO Hook for long stack traces to be made here.
1011

    
1012
  TryCatch try_catch;
1013

    
1014
  if (enter_symbol.IsEmpty()) {
1015
    enter_symbol = NODE_PSYMBOL("enter");
1016
    exit_symbol = NODE_PSYMBOL("exit");
1017
    disposed_symbol = NODE_PSYMBOL("_disposed");
1018
  }
1019

    
1020
  Local<Value> domain_v = object->Get(domain_symbol);
1021
  Local<Object> domain;
1022
  Local<Function> enter;
1023
  Local<Function> exit;
1024
  if (!domain_v->IsUndefined()) {
1025
    domain = domain_v->ToObject();
1026
    if (domain->Get(disposed_symbol)->BooleanValue()) {
1027
      // domain has been disposed of.
1028
      return Undefined();
1029
    }
1030
    enter = Local<Function>::Cast(domain->Get(enter_symbol));
1031
    enter->Call(domain, 0, NULL);
1032
  }
1033

    
1034
  if (try_catch.HasCaught()) {
1035
    FatalException(try_catch);
1036
    return Undefined();
1037
  }
1038

    
1039
  Local<Value> ret = callback->Call(object, argc, argv);
1040

    
1041
  if (try_catch.HasCaught()) {
1042
    FatalException(try_catch);
1043
    return Undefined();
1044
  }
1045

    
1046
  if (!domain_v->IsUndefined()) {
1047
    exit = Local<Function>::Cast(domain->Get(exit_symbol));
1048
    exit->Call(domain, 0, NULL);
1049
  }
1050

    
1051
  if (try_catch.HasCaught()) {
1052
    FatalException(try_catch);
1053
    return Undefined();
1054
  }
1055

    
1056
  return scope.Close(ret);
1057
}
1058

    
1059

    
1060
void SetErrno(uv_err_t err) {
1061
  HandleScope scope;
1062

    
1063
  if (errno_symbol.IsEmpty()) {
1064
    errno_symbol = NODE_PSYMBOL("errno");
1065
  }
1066

    
1067
  if (err.code == UV_UNKNOWN) {
1068
    char errno_buf[100];
1069
    snprintf(errno_buf, 100, "Unknown system errno %d", err.sys_errno_);
1070
    Context::GetCurrent()->Global()->Set(errno_symbol, String::New(errno_buf));
1071
  } else {
1072
    Context::GetCurrent()->Global()->Set(errno_symbol,
1073
                                         String::NewSymbol(uv_err_name(err)));
1074
  }
1075
}
1076

    
1077

    
1078
enum encoding ParseEncoding(Handle<Value> encoding_v, enum encoding _default) {
1079
  HandleScope scope;
1080

    
1081
  if (!encoding_v->IsString()) return _default;
1082

    
1083
  String::Utf8Value encoding(encoding_v);
1084

    
1085
  if (strcasecmp(*encoding, "utf8") == 0) {
1086
    return UTF8;
1087
  } else if (strcasecmp(*encoding, "utf-8") == 0) {
1088
    return UTF8;
1089
  } else if (strcasecmp(*encoding, "ascii") == 0) {
1090
    return ASCII;
1091
  } else if (strcasecmp(*encoding, "base64") == 0) {
1092
    return BASE64;
1093
  } else if (strcasecmp(*encoding, "ucs2") == 0) {
1094
    return UCS2;
1095
  } else if (strcasecmp(*encoding, "ucs-2") == 0) {
1096
    return UCS2;
1097
  } else if (strcasecmp(*encoding, "binary") == 0) {
1098
    return BINARY;
1099
  } else if (strcasecmp(*encoding, "hex") == 0) {
1100
    return HEX;
1101
  } else if (strcasecmp(*encoding, "raw") == 0) {
1102
    fprintf(stderr, "'raw' (array of integers) has been removed. "
1103
                    "Use 'binary'.\n");
1104
    return BINARY;
1105
  } else if (strcasecmp(*encoding, "raws") == 0) {
1106
    fprintf(stderr, "'raws' encoding has been renamed to 'binary'. "
1107
                    "Please update your code.\n");
1108
    return BINARY;
1109
  } else {
1110
    return _default;
1111
  }
1112
}
1113

    
1114
Local<Value> Encode(const void *buf, size_t len, enum encoding encoding) {
1115
  HandleScope scope;
1116

    
1117
  if (!len) return scope.Close(String::Empty());
1118

    
1119
  if (encoding == BINARY) {
1120
    const unsigned char *cbuf = static_cast<const unsigned char*>(buf);
1121
    uint16_t * twobytebuf = new uint16_t[len];
1122
    for (size_t i = 0; i < len; i++) {
1123
      // XXX is the following line platform independent?
1124
      twobytebuf[i] = cbuf[i];
1125
    }
1126
    Local<String> chunk = String::New(twobytebuf, len);
1127
    delete [] twobytebuf; // TODO use ExternalTwoByteString?
1128
    return scope.Close(chunk);
1129
  }
1130

    
1131
  // utf8 or ascii encoding
1132
  Local<String> chunk = String::New((const char*)buf, len);
1133
  return scope.Close(chunk);
1134
}
1135

    
1136
// Returns -1 if the handle was not valid for decoding
1137
ssize_t DecodeBytes(v8::Handle<v8::Value> val, enum encoding encoding) {
1138
  HandleScope scope;
1139

    
1140
  if (val->IsArray()) {
1141
    fprintf(stderr, "'raw' encoding (array of integers) has been removed. "
1142
                    "Use 'binary'.\n");
1143
    assert(0);
1144
    return -1;
1145
  }
1146

    
1147
  if (encoding == BINARY && Buffer::HasInstance(val)) {
1148
    return Buffer::Length(val->ToObject());
1149
  }
1150

    
1151
  Local<String> str = val->ToString();
1152

    
1153
  if (encoding == UTF8) return str->Utf8Length();
1154
  else if (encoding == UCS2) return str->Length() * 2;
1155
  else if (encoding == HEX) return str->Length() / 2;
1156

    
1157
  return str->Length();
1158
}
1159

    
1160
#ifndef MIN
1161
# define MIN(a, b) ((a) < (b) ? (a) : (b))
1162
#endif
1163

    
1164
// Returns number of bytes written.
1165
ssize_t DecodeWrite(char *buf,
1166
                    size_t buflen,
1167
                    v8::Handle<v8::Value> val,
1168
                    enum encoding encoding) {
1169
  HandleScope scope;
1170

    
1171
  // XXX
1172
  // A lot of improvement can be made here. See:
1173
  // http://code.google.com/p/v8/issues/detail?id=270
1174
  // http://groups.google.com/group/v8-dev/browse_thread/thread/dba28a81d9215291/ece2b50a3b4022c
1175
  // http://groups.google.com/group/v8-users/browse_thread/thread/1f83b0ba1f0a611
1176

    
1177
  if (val->IsArray()) {
1178
    fprintf(stderr, "'raw' encoding (array of integers) has been removed. "
1179
                    "Use 'binary'.\n");
1180
    assert(0);
1181
    return -1;
1182
  }
1183

    
1184
  Local<String> str = val->ToString();
1185

    
1186
  if (encoding == UTF8) {
1187
    str->WriteUtf8(buf, buflen, NULL, String::HINT_MANY_WRITES_EXPECTED);
1188
    return buflen;
1189
  }
1190

    
1191
  if (encoding == ASCII) {
1192
    str->WriteAscii(buf, 0, buflen, String::HINT_MANY_WRITES_EXPECTED);
1193
    return buflen;
1194
  }
1195

    
1196
  // THIS IS AWFUL!!! FIXME
1197

    
1198
  assert(encoding == BINARY);
1199

    
1200
  uint16_t * twobytebuf = new uint16_t[buflen];
1201

    
1202
  str->Write(twobytebuf, 0, buflen, String::HINT_MANY_WRITES_EXPECTED);
1203

    
1204
  for (size_t i = 0; i < buflen; i++) {
1205
    unsigned char *b = reinterpret_cast<unsigned char*>(&twobytebuf[i]);
1206
    buf[i] = b[0];
1207
  }
1208

    
1209
  delete [] twobytebuf;
1210

    
1211
  return buflen;
1212
}
1213

    
1214

    
1215
void DisplayExceptionLine (TryCatch &try_catch) {
1216
  HandleScope scope;
1217

    
1218
  Handle<Message> message = try_catch.Message();
1219

    
1220
  uv_tty_reset_mode();
1221

    
1222
  fprintf(stderr, "\n");
1223

    
1224
  if (!message.IsEmpty()) {
1225
    // Print (filename):(line number): (message).
1226
    String::Utf8Value filename(message->GetScriptResourceName());
1227
    const char* filename_string = *filename;
1228
    int linenum = message->GetLineNumber();
1229
    fprintf(stderr, "%s:%i\n", filename_string, linenum);
1230
    // Print line of source code.
1231
    String::Utf8Value sourceline(message->GetSourceLine());
1232
    const char* sourceline_string = *sourceline;
1233

    
1234
    // HACK HACK HACK
1235
    //
1236
    // FIXME
1237
    //
1238
    // Because of how CommonJS modules work, all scripts are wrapped with a
1239
    // "function (function (exports, __filename, ...) {"
1240
    // to provide script local variables.
1241
    //
1242
    // When reporting errors on the first line of a script, this wrapper
1243
    // function is leaked to the user. This HACK is to remove it. The length
1244
    // of the wrapper is 62. That wrapper is defined in src/node.js
1245
    //
1246
    // If that wrapper is ever changed, then this number also has to be
1247
    // updated. Or - someone could clean this up so that the two peices
1248
    // don't need to be changed.
1249
    //
1250
    // Even better would be to get support into V8 for wrappers that
1251
    // shouldn't be reported to users.
1252
    int offset = linenum == 1 ? 62 : 0;
1253

    
1254
    fprintf(stderr, "%s\n", sourceline_string + offset);
1255
    // Print wavy underline (GetUnderline is deprecated).
1256
    int start = message->GetStartColumn();
1257
    for (int i = offset; i < start; i++) {
1258
      fputc((sourceline_string[i] == '\t') ? '\t' : ' ', stderr);
1259
    }
1260
    int end = message->GetEndColumn();
1261
    for (int i = start; i < end; i++) {
1262
      fputc('^', stderr);
1263
    }
1264
    fputc('\n', stderr);
1265
  }
1266
}
1267

    
1268

    
1269
static void ReportException(TryCatch &try_catch, bool show_line) {
1270
  HandleScope scope;
1271

    
1272
  if (show_line) DisplayExceptionLine(try_catch);
1273

    
1274
  String::Utf8Value trace(try_catch.StackTrace());
1275

    
1276
  // range errors have a trace member set to undefined
1277
  if (trace.length() > 0 && !try_catch.StackTrace()->IsUndefined()) {
1278
    fprintf(stderr, "%s\n", *trace);
1279
  } else {
1280
    // this really only happens for RangeErrors, since they're the only
1281
    // kind that won't have all this info in the trace, or when non-Error
1282
    // objects are thrown manually.
1283
    Local<Value> er = try_catch.Exception();
1284
    bool isErrorObject = er->IsObject() &&
1285
      !(er->ToObject()->Get(String::New("message"))->IsUndefined()) &&
1286
      !(er->ToObject()->Get(String::New("name"))->IsUndefined());
1287

    
1288
    if (isErrorObject) {
1289
      String::Utf8Value name(er->ToObject()->Get(String::New("name")));
1290
      fprintf(stderr, "%s: ", *name);
1291
    }
1292

    
1293
    String::Utf8Value msg(!isErrorObject ? er
1294
                         : er->ToObject()->Get(String::New("message")));
1295
    fprintf(stderr, "%s\n", *msg);
1296
  }
1297

    
1298
  fflush(stderr);
1299
}
1300

    
1301
// Executes a str within the current v8 context.
1302
Local<Value> ExecuteString(Handle<String> source, Handle<Value> filename) {
1303
  HandleScope scope;
1304
  TryCatch try_catch;
1305

    
1306
  Local<v8::Script> script = v8::Script::Compile(source, filename);
1307
  if (script.IsEmpty()) {
1308
    ReportException(try_catch, true);
1309
    exit(1);
1310
  }
1311

    
1312
  Local<Value> result = script->Run();
1313
  if (result.IsEmpty()) {
1314
    ReportException(try_catch, true);
1315
    exit(1);
1316
  }
1317

    
1318
  return scope.Close(result);
1319
}
1320

    
1321

    
1322
static Handle<Value> GetActiveRequests(const Arguments& args) {
1323
  HandleScope scope;
1324

    
1325
  Local<Array> ary = Array::New();
1326
  ngx_queue_t* q = NULL;
1327
  int i = 0;
1328

    
1329
  ngx_queue_foreach(q, &req_wrap_queue) {
1330
    ReqWrap<uv_req_t>* w = container_of(q, ReqWrap<uv_req_t>, req_wrap_queue_);
1331
    if (w->object_.IsEmpty()) continue;
1332
    ary->Set(i++, w->object_);
1333
  }
1334

    
1335
  return scope.Close(ary);
1336
}
1337

    
1338

    
1339
// Non-static, friend of HandleWrap. Could have been a HandleWrap method but
1340
// implemented here for consistency with GetActiveRequests().
1341
Handle<Value> GetActiveHandles(const Arguments& args) {
1342
  HandleScope scope;
1343

    
1344
  Local<Array> ary = Array::New();
1345
  ngx_queue_t* q = NULL;
1346
  int i = 0;
1347

    
1348
  Local<String> owner_sym = String::New("owner");
1349

    
1350
  ngx_queue_foreach(q, &handle_wrap_queue) {
1351
    HandleWrap* w = container_of(q, HandleWrap, handle_wrap_queue_);
1352
    if (w->object_.IsEmpty() || w->unref_) continue;
1353
    Local<Value> obj = w->object_->Get(owner_sym);
1354
    if (obj->IsUndefined()) obj = *w->object_;
1355
    ary->Set(i++, obj);
1356
  }
1357

    
1358
  return scope.Close(ary);
1359
}
1360

    
1361

    
1362
static Handle<Value> Abort(const Arguments& args) {
1363
  abort();
1364
  return Undefined();
1365
}
1366

    
1367

    
1368
static Handle<Value> Chdir(const Arguments& args) {
1369
  HandleScope scope;
1370

    
1371
  if (args.Length() != 1 || !args[0]->IsString()) {
1372
    return ThrowException(Exception::Error(String::New("Bad argument.")));
1373
  }
1374

    
1375
  String::Utf8Value path(args[0]);
1376

    
1377
  uv_err_t r = uv_chdir(*path);
1378

    
1379
  if (r.code != UV_OK) {
1380
    return ThrowException(UVException(r.code, "uv_chdir"));
1381
  }
1382

    
1383
  return Undefined();
1384
}
1385

    
1386

    
1387
static Handle<Value> Cwd(const Arguments& args) {
1388
  HandleScope scope;
1389
#ifdef _WIN32
1390
  /* MAX_PATH is in characters, not bytes. Make sure we have enough headroom. */
1391
  char buf[MAX_PATH * 4 + 1];
1392
#else
1393
  char buf[PATH_MAX + 1];
1394
#endif
1395

    
1396
  uv_err_t r = uv_cwd(buf, ARRAY_SIZE(buf) - 1);
1397
  if (r.code != UV_OK) {
1398
    return ThrowException(UVException(r.code, "uv_cwd"));
1399
  }
1400

    
1401
  buf[ARRAY_SIZE(buf) - 1] = '\0';
1402
  Local<String> cwd = String::New(buf);
1403

    
1404
  return scope.Close(cwd);
1405
}
1406

    
1407

    
1408
static Handle<Value> Umask(const Arguments& args) {
1409
  HandleScope scope;
1410
  unsigned int old;
1411

    
1412
  if (args.Length() < 1 || args[0]->IsUndefined()) {
1413
    old = umask(0);
1414
    umask((mode_t)old);
1415

    
1416
  } else if(!args[0]->IsInt32() && !args[0]->IsString()) {
1417
    return ThrowException(Exception::TypeError(
1418
          String::New("argument must be an integer or octal string.")));
1419

    
1420
  } else {
1421
    int oct;
1422
    if(args[0]->IsInt32()) {
1423
      oct = args[0]->Uint32Value();
1424
    } else {
1425
      oct = 0;
1426
      String::Utf8Value str(args[0]);
1427

    
1428
      // Parse the octal string.
1429
      for (int i = 0; i < str.length(); i++) {
1430
        char c = (*str)[i];
1431
        if (c > '7' || c < '0') {
1432
          return ThrowException(Exception::TypeError(
1433
                String::New("invalid octal string")));
1434
        }
1435
        oct *= 8;
1436
        oct += c - '0';
1437
      }
1438
    }
1439
    old = umask(static_cast<mode_t>(oct));
1440
  }
1441

    
1442
  return scope.Close(Uint32::New(old));
1443
}
1444

    
1445

    
1446
#ifdef __POSIX__
1447

    
1448
static Handle<Value> GetUid(const Arguments& args) {
1449
  HandleScope scope;
1450
  int uid = getuid();
1451
  return scope.Close(Integer::New(uid));
1452
}
1453

    
1454

    
1455
static Handle<Value> GetGid(const Arguments& args) {
1456
  HandleScope scope;
1457
  int gid = getgid();
1458
  return scope.Close(Integer::New(gid));
1459
}
1460

    
1461

    
1462
static Handle<Value> SetGid(const Arguments& args) {
1463
  HandleScope scope;
1464

    
1465
  if (args.Length() < 1) {
1466
    return ThrowException(Exception::Error(
1467
      String::New("setgid requires 1 argument")));
1468
  }
1469

    
1470
  int gid;
1471

    
1472
  if (args[0]->IsNumber()) {
1473
    gid = args[0]->Int32Value();
1474
  } else if (args[0]->IsString()) {
1475
    String::Utf8Value grpnam(args[0]);
1476
    struct group grp, *grpp = NULL;
1477
    int err;
1478

    
1479
    if ((err = getgrnam_r(*grpnam, &grp, getbuf, ARRAY_SIZE(getbuf), &grpp)) ||
1480
        grpp == NULL) {
1481
      if (errno == 0)
1482
        return ThrowException(Exception::Error(
1483
          String::New("setgid group id does not exist")));
1484
      else
1485
        return ThrowException(ErrnoException(errno, "getgrnam_r"));
1486
    }
1487

    
1488
    gid = grpp->gr_gid;
1489
  } else {
1490
    return ThrowException(Exception::Error(
1491
      String::New("setgid argument must be a number or a string")));
1492
  }
1493

    
1494
  int result;
1495
  if ((result = setgid(gid)) != 0) {
1496
    return ThrowException(ErrnoException(errno, "setgid"));
1497
  }
1498
  return Undefined();
1499
}
1500

    
1501

    
1502
static Handle<Value> SetUid(const Arguments& args) {
1503
  HandleScope scope;
1504

    
1505
  if (args.Length() < 1) {
1506
    return ThrowException(Exception::Error(
1507
          String::New("setuid requires 1 argument")));
1508
  }
1509

    
1510
  int uid;
1511

    
1512
  if (args[0]->IsNumber()) {
1513
    uid = args[0]->Int32Value();
1514
  } else if (args[0]->IsString()) {
1515
    String::Utf8Value pwnam(args[0]);
1516
    struct passwd pwd, *pwdp = NULL;
1517
    int err;
1518

    
1519
    if ((err = getpwnam_r(*pwnam, &pwd, getbuf, ARRAY_SIZE(getbuf), &pwdp)) ||
1520
        pwdp == NULL) {
1521
      if (errno == 0)
1522
        return ThrowException(Exception::Error(
1523
          String::New("setuid user id does not exist")));
1524
      else
1525
        return ThrowException(ErrnoException(errno, "getpwnam_r"));
1526
    }
1527

    
1528
    uid = pwdp->pw_uid;
1529
  } else {
1530
    return ThrowException(Exception::Error(
1531
      String::New("setuid argument must be a number or a string")));
1532
  }
1533

    
1534
  int result;
1535
  if ((result = setuid(uid)) != 0) {
1536
    return ThrowException(ErrnoException(errno, "setuid"));
1537
  }
1538
  return Undefined();
1539
}
1540

    
1541

    
1542
#endif // __POSIX__
1543

    
1544

    
1545
v8::Handle<v8::Value> Exit(const v8::Arguments& args) {
1546
  HandleScope scope;
1547
  exit(args[0]->IntegerValue());
1548
  return Undefined();
1549
}
1550

    
1551

    
1552
static void CheckStatus(uv_timer_t* watcher, int status) {
1553
  assert(watcher == &gc_timer);
1554

    
1555
  // check memory
1556
  if (!uv_is_active((uv_handle_t*) &gc_idle)) {
1557
    HeapStatistics stats;
1558
    V8::GetHeapStatistics(&stats);
1559
    if (stats.total_heap_size() > 1024 * 1024 * 128) {
1560
      // larger than 128 megs, just start the idle watcher
1561
      uv_idle_start(&gc_idle, node::Idle);
1562
      return;
1563
    }
1564
  }
1565

    
1566
  double d = uv_now(uv_default_loop()) - TICK_TIME(3);
1567

    
1568
  //printfb("timer d = %f\n", d);
1569

    
1570
  if (d  >= GC_WAIT_TIME - 1.) {
1571
    //fprintf(stderr, "start idle\n");
1572
    uv_idle_start(&gc_idle, node::Idle);
1573
  }
1574
}
1575

    
1576

    
1577
static Handle<Value> Uptime(const Arguments& args) {
1578
  HandleScope scope;
1579
  double uptime;
1580

    
1581
  uv_err_t err = uv_uptime(&uptime);
1582

    
1583
  if (err.code != UV_OK) {
1584
    return Undefined();
1585
  }
1586

    
1587
  return scope.Close(Number::New(uptime - prog_start_time));
1588
}
1589

    
1590

    
1591
v8::Handle<v8::Value> UVCounters(const v8::Arguments& args) {
1592
  HandleScope scope;
1593

    
1594
  uv_counters_t* c = &uv_default_loop()->counters;
1595

    
1596
  Local<Object> obj = Object::New();
1597

    
1598
#define setc(name) \
1599
    obj->Set(String::New(#name), Integer::New(static_cast<int32_t>(c->name)));
1600

    
1601
  setc(eio_init)
1602
  setc(req_init)
1603
  setc(handle_init)
1604
  setc(stream_init)
1605
  setc(tcp_init)
1606
  setc(udp_init)
1607
  setc(pipe_init)
1608
  setc(tty_init)
1609
  setc(prepare_init)
1610
  setc(check_init)
1611
  setc(idle_init)
1612
  setc(async_init)
1613
  setc(timer_init)
1614
  setc(process_init)
1615
  setc(fs_event_init)
1616

    
1617
#undef setc
1618

    
1619
  return scope.Close(obj);
1620
}
1621

    
1622

    
1623
v8::Handle<v8::Value> MemoryUsage(const v8::Arguments& args) {
1624
  HandleScope scope;
1625

    
1626
  size_t rss;
1627

    
1628
  uv_err_t err = uv_resident_set_memory(&rss);
1629

    
1630
  if (err.code != UV_OK) {
1631
    return ThrowException(UVException(err.code, "uv_resident_set_memory"));
1632
  }
1633

    
1634
  Local<Object> info = Object::New();
1635

    
1636
  if (rss_symbol.IsEmpty()) {
1637
    rss_symbol = NODE_PSYMBOL("rss");
1638
    heap_total_symbol = NODE_PSYMBOL("heapTotal");
1639
    heap_used_symbol = NODE_PSYMBOL("heapUsed");
1640
  }
1641

    
1642
  info->Set(rss_symbol, Number::New(rss));
1643

    
1644
  // V8 memory usage
1645
  HeapStatistics v8_heap_stats;
1646
  V8::GetHeapStatistics(&v8_heap_stats);
1647
  info->Set(heap_total_symbol,
1648
            Integer::NewFromUnsigned(v8_heap_stats.total_heap_size()));
1649
  info->Set(heap_used_symbol,
1650
            Integer::NewFromUnsigned(v8_heap_stats.used_heap_size()));
1651

    
1652
  return scope.Close(info);
1653
}
1654

    
1655

    
1656
Handle<Value> Kill(const Arguments& args) {
1657
  HandleScope scope;
1658

    
1659
  if (args.Length() != 2) {
1660
    return ThrowException(Exception::Error(String::New("Bad argument.")));
1661
  }
1662

    
1663
  int pid = args[0]->IntegerValue();
1664
  int sig = args[1]->Int32Value();
1665
  uv_err_t err = uv_kill(pid, sig);
1666

    
1667
  if (err.code != UV_OK) {
1668
    SetErrno(err);
1669
    return scope.Close(Integer::New(-1));
1670
  }
1671

    
1672
  return Undefined();
1673
}
1674

    
1675
// used in Hrtime() below
1676
#define NANOS_PER_SEC 1000000000
1677

    
1678
// Hrtime exposes libuv's uv_hrtime() high-resolution timer.
1679
// The value returned by uv_hrtime() is a 64-bit int representing nanoseconds,
1680
// so this function instead returns an Array with 2 entries representing seconds
1681
// and nanoseconds, to avoid any integer overflow possibility.
1682
// Pass in an Array from a previous hrtime() call to instead get a time diff.
1683
Handle<Value> Hrtime(const v8::Arguments& args) {
1684
  HandleScope scope;
1685

    
1686
  uint64_t t = uv_hrtime();
1687

    
1688
  if (args.Length() > 0) {
1689
    // return a time diff tuple
1690
    Local<Array> inArray = Local<Array>::Cast(args[0]);
1691
    uint64_t seconds = inArray->Get(0)->Uint32Value();
1692
    uint64_t nanos = inArray->Get(1)->Uint32Value();
1693
    t -= (seconds * NANOS_PER_SEC) + nanos;
1694
  }
1695

    
1696
  Local<Array> tuple = Array::New(2);
1697
  tuple->Set(0, Integer::NewFromUnsigned(t / NANOS_PER_SEC));
1698
  tuple->Set(1, Integer::NewFromUnsigned(t % NANOS_PER_SEC));
1699

    
1700
  return scope.Close(tuple);
1701
}
1702

    
1703

    
1704
typedef void (UV_DYNAMIC* extInit)(Handle<Object> exports);
1705

    
1706
// DLOpen is node.dlopen(). Used to load 'module.node' dynamically shared
1707
// objects.
1708
Handle<Value> DLOpen(const v8::Arguments& args) {
1709
  HandleScope scope;
1710
  char symbol[1024], *base, *pos;
1711
  uv_lib_t lib;
1712
  node_module_struct compat_mod;
1713
  int r;
1714

    
1715
  if (args.Length() < 2) {
1716
    Local<Value> exception = Exception::Error(
1717
        String::New("process.dlopen takes exactly 2 arguments."));
1718
    return ThrowException(exception);
1719
  }
1720

    
1721
  String::Utf8Value filename(args[0]); // Cast
1722
  Local<Object> target = args[1]->ToObject(); // Cast
1723

    
1724
  if (uv_dlopen(*filename, &lib)) {
1725
    Local<String> errmsg = String::New(uv_dlerror(&lib));
1726
#ifdef _WIN32
1727
    // Windows needs to add the filename into the error message
1728
    errmsg = String::Concat(errmsg, args[0]->ToString());
1729
#endif
1730
    return ThrowException(Exception::Error(errmsg));
1731
  }
1732

    
1733
  String::Utf8Value path(args[0]);
1734
  base = *path;
1735

    
1736
  /* Find the shared library filename within the full path. */
1737
#ifdef __POSIX__
1738
  pos = strrchr(base, '/');
1739
  if (pos != NULL) {
1740
    base = pos + 1;
1741
  }
1742
#else // Windows
1743
  for (;;) {
1744
    pos = strpbrk(base, "\\/:");
1745
    if (pos == NULL) {
1746
      break;
1747
    }
1748
    base = pos + 1;
1749
  }
1750
#endif
1751

    
1752
  /* Strip the .node extension. */
1753
  pos = strrchr(base, '.');
1754
  if (pos != NULL) {
1755
    *pos = '\0';
1756
  }
1757

    
1758
  /* Add the `_module` suffix to the extension name. */
1759
  r = snprintf(symbol, sizeof symbol, "%s_module", base);
1760
  if (r <= 0 || static_cast<size_t>(r) >= sizeof symbol) {
1761
    Local<Value> exception =
1762
        Exception::Error(String::New("Out of memory."));
1763
    return ThrowException(exception);
1764
  }
1765

    
1766
  // Get the init() function from the dynamically shared object.
1767
  node_module_struct *mod;
1768
  if (uv_dlsym(&lib, symbol, reinterpret_cast<void**>(&mod))) {
1769
    /* Start Compatibility hack: Remove once everyone is using NODE_MODULE macro */
1770
    memset(&compat_mod, 0, sizeof compat_mod);
1771

    
1772
    mod = &compat_mod;
1773
    mod->version = NODE_MODULE_VERSION;
1774

    
1775
    if (uv_dlsym(&lib, "init", reinterpret_cast<void**>(&mod->register_func))) {
1776
      Local<String> errmsg = String::New(uv_dlerror(&lib));
1777
      uv_dlclose(&lib);
1778
      return ThrowException(Exception::Error(errmsg));
1779
    }
1780
    /* End Compatibility hack */
1781
  }
1782

    
1783
  if (mod->version != NODE_MODULE_VERSION) {
1784
    Local<Value> exception = Exception::Error(
1785
        String::New("Module version mismatch, refusing to load."));
1786
    return ThrowException(exception);
1787
  }
1788

    
1789
  // Execute the C++ module
1790
  mod->register_func(target);
1791

    
1792
  // Tell coverity that 'handle' should not be freed when we return.
1793
  // coverity[leaked_storage]
1794
  return Undefined();
1795
}
1796

    
1797

    
1798
static void OnFatalError(const char* location, const char* message) {
1799
  if (location) {
1800
    fprintf(stderr, "FATAL ERROR: %s %s\n", location, message);
1801
  } else {
1802
    fprintf(stderr, "FATAL ERROR: %s\n", message);
1803
  }
1804
  exit(1);
1805
}
1806

    
1807
void FatalException(TryCatch &try_catch) {
1808
  HandleScope scope;
1809

    
1810
  if (listeners_symbol.IsEmpty()) {
1811
    listeners_symbol = NODE_PSYMBOL("listeners");
1812
    uncaught_exception_symbol = NODE_PSYMBOL("uncaughtException");
1813
    emit_symbol = NODE_PSYMBOL("emit");
1814
  }
1815

    
1816
  Local<Value> listeners_v = process->Get(listeners_symbol);
1817
  assert(listeners_v->IsFunction());
1818

    
1819
  Local<Function> listeners = Local<Function>::Cast(listeners_v);
1820

    
1821
  Local<String> uncaught_exception_symbol_l = Local<String>::New(uncaught_exception_symbol);
1822
  Local<Value> argv[1] = { uncaught_exception_symbol_l  };
1823
  Local<Value> ret = listeners->Call(process, 1, argv);
1824

    
1825
  assert(ret->IsArray());
1826

    
1827
  Local<Array> listener_array = Local<Array>::Cast(ret);
1828

    
1829
  uint32_t length = listener_array->Length();
1830
  // Report and exit if process has no "uncaughtException" listener
1831
  if (length == 0) {
1832
    ReportException(try_catch, true);
1833
    exit(1);
1834
  }
1835

    
1836
  // Otherwise fire the process "uncaughtException" event
1837
  Local<Value> emit_v = process->Get(emit_symbol);
1838
  assert(emit_v->IsFunction());
1839

    
1840
  Local<Function> emit = Local<Function>::Cast(emit_v);
1841

    
1842
  Local<Value> error = try_catch.Exception();
1843
  Local<Value> event_argv[2] = { uncaught_exception_symbol_l, error };
1844

    
1845
  TryCatch event_try_catch;
1846
  emit->Call(process, 2, event_argv);
1847

    
1848
  if (event_try_catch.HasCaught()) {
1849
    // the uncaught exception event threw, so we must exit.
1850
    ReportException(event_try_catch, true);
1851
    exit(1);
1852
  }
1853

    
1854
  // This makes sure uncaught exceptions don't interfere with process.nextTick
1855
  StartTickSpinner();
1856
}
1857

    
1858

    
1859
Persistent<Object> binding_cache;
1860
Persistent<Array> module_load_list;
1861

    
1862
static Handle<Value> Binding(const Arguments& args) {
1863
  HandleScope scope;
1864

    
1865
  Local<String> module = args[0]->ToString();
1866
  String::Utf8Value module_v(module);
1867
  node_module_struct* modp;
1868

    
1869
  if (binding_cache.IsEmpty()) {
1870
    binding_cache = Persistent<Object>::New(Object::New());
1871
  }
1872

    
1873
  Local<Object> exports;
1874

    
1875
  if (binding_cache->Has(module)) {
1876
    exports = binding_cache->Get(module)->ToObject();
1877
    return scope.Close(exports);
1878
  }
1879

    
1880
  // Append a string to process.moduleLoadList
1881
  char buf[1024];
1882
  snprintf(buf, 1024, "Binding %s", *module_v);
1883
  uint32_t l = module_load_list->Length();
1884
  module_load_list->Set(l, String::New(buf));
1885

    
1886
  if ((modp = get_builtin_module(*module_v)) != NULL) {
1887
    exports = Object::New();
1888
    modp->register_func(exports);
1889
    binding_cache->Set(module, exports);
1890

    
1891
  } else if (!strcmp(*module_v, "constants")) {
1892
    exports = Object::New();
1893
    DefineConstants(exports);
1894
    binding_cache->Set(module, exports);
1895

    
1896
#ifdef __POSIX__
1897
  } else if (!strcmp(*module_v, "io_watcher")) {
1898
    exports = Object::New();
1899
    IOWatcher::Initialize(exports);
1900
    binding_cache->Set(module, exports);
1901
#endif
1902

    
1903
  } else if (!strcmp(*module_v, "natives")) {
1904
    exports = Object::New();
1905
    DefineJavaScript(exports);
1906
    binding_cache->Set(module, exports);
1907

    
1908
  } else {
1909

    
1910
    return ThrowException(Exception::Error(String::New("No such module")));
1911
  }
1912

    
1913
  return scope.Close(exports);
1914
}
1915

    
1916

    
1917
static Handle<Value> ProcessTitleGetter(Local<String> property,
1918
                                        const AccessorInfo& info) {
1919
  HandleScope scope;
1920
  char buffer[512];
1921
  uv_get_process_title(buffer, sizeof(buffer));
1922
  return scope.Close(String::New(buffer));
1923
}
1924

    
1925

    
1926
static void ProcessTitleSetter(Local<String> property,
1927
                               Local<Value> value,
1928
                               const AccessorInfo& info) {
1929
  HandleScope scope;
1930
  String::Utf8Value title(value);
1931
  // TODO: protect with a lock
1932
  uv_set_process_title(*title);
1933
}
1934

    
1935

    
1936
static Handle<Value> EnvGetter(Local<String> property,
1937
                               const AccessorInfo& info) {
1938
  HandleScope scope;
1939
#ifdef __POSIX__
1940
  String::Utf8Value key(property);
1941
  const char* val = getenv(*key);
1942
  if (val) {
1943
    return scope.Close(String::New(val));
1944
  }
1945
#else  // _WIN32
1946
  String::Value key(property);
1947
  WCHAR buffer[32767]; // The maximum size allowed for environment variables.
1948
  DWORD result = GetEnvironmentVariableW(reinterpret_cast<WCHAR*>(*key),
1949
                                         buffer,
1950
                                         ARRAY_SIZE(buffer));
1951
  // If result >= sizeof buffer the buffer was too small. That should never
1952
  // happen. If result == 0 and result != ERROR_SUCCESS the variable was not
1953
  // not found.
1954
  if ((result > 0 || GetLastError() == ERROR_SUCCESS) &&
1955
      result < ARRAY_SIZE(buffer)) {
1956
    return scope.Close(String::New(reinterpret_cast<uint16_t*>(buffer), result));
1957
  }
1958
#endif
1959
  // Not found
1960
  return Undefined();
1961
}
1962

    
1963

    
1964
static Handle<Value> EnvSetter(Local<String> property,
1965
                               Local<Value> value,
1966
                               const AccessorInfo& info) {
1967
  HandleScope scope;
1968
#ifdef __POSIX__
1969
  String::Utf8Value key(property);
1970
  String::Utf8Value val(value);
1971
  setenv(*key, *val, 1);
1972
#else  // _WIN32
1973
  String::Value key(property);
1974
  String::Value val(value);
1975
  WCHAR* key_ptr = reinterpret_cast<WCHAR*>(*key);
1976
  // Environment variables that start with '=' are read-only.
1977
  if (key_ptr[0] != L'=') {
1978
    SetEnvironmentVariableW(key_ptr, reinterpret_cast<WCHAR*>(*val));
1979
  }
1980
#endif
1981
  // Whether it worked or not, always return rval.
1982
  return scope.Close(value);
1983
}
1984

    
1985

    
1986
static Handle<Integer> EnvQuery(Local<String> property,
1987
                                const AccessorInfo& info) {
1988
  HandleScope scope;
1989
#ifdef __POSIX__
1990
  String::Utf8Value key(property);
1991
  if (getenv(*key)) {
1992
    return scope.Close(Integer::New(None));
1993
  }
1994
#else  // _WIN32
1995
  String::Value key(property);
1996
  WCHAR* key_ptr = reinterpret_cast<WCHAR*>(*key);
1997
  if (GetEnvironmentVariableW(key_ptr, NULL, 0) > 0 ||
1998
      GetLastError() == ERROR_SUCCESS) {
1999
    if (key_ptr[0] == L'=') {
2000
      // Environment variables that start with '=' are hidden and read-only.
2001
      return scope.Close(Integer::New(v8::ReadOnly ||
2002
                                      v8::DontDelete ||
2003
                                      v8::DontEnum));
2004
    } else {
2005
      return scope.Close(Integer::New(None));
2006
    }
2007
  }
2008
#endif
2009
  // Not found
2010
  return scope.Close(Handle<Integer>());
2011
}
2012

    
2013

    
2014
static Handle<Boolean> EnvDeleter(Local<String> property,
2015
                                  const AccessorInfo& info) {
2016
  HandleScope scope;
2017
#ifdef __POSIX__
2018
  String::Utf8Value key(property);
2019
  if (!getenv(*key)) return False();
2020
  unsetenv(*key); // can't check return value, it's void on some platforms
2021
  return True();
2022
#else
2023
  String::Value key(property);
2024
  WCHAR* key_ptr = reinterpret_cast<WCHAR*>(*key);
2025
  if (key_ptr[0] == L'=' || !SetEnvironmentVariableW(key_ptr, NULL)) {
2026
    // Deletion failed. Return true if the key wasn't there in the first place,
2027
    // false if it is still there.
2028
    bool rv = GetEnvironmentVariableW(key_ptr, NULL, NULL) == 0 &&
2029
              GetLastError() != ERROR_SUCCESS;
2030
    return scope.Close(Boolean::New(rv));
2031
  }
2032
  return True();
2033
#endif
2034
}
2035

    
2036

    
2037
static Handle<Array> EnvEnumerator(const AccessorInfo& info) {
2038
  HandleScope scope;
2039
#ifdef __POSIX__
2040
  int size = 0;
2041
  while (environ[size]) size++;
2042

    
2043
  Local<Array> env = Array::New(size);
2044

    
2045
  for (int i = 0; i < size; ++i) {
2046
    const char* var = environ[i];
2047
    const char* s = strchr(var, '=');
2048
    const int length = s ? s - var : strlen(var);
2049
    env->Set(i, String::New(var, length));
2050
  }
2051
#else  // _WIN32
2052
  WCHAR* environment = GetEnvironmentStringsW();
2053
  if (environment == NULL) {
2054
    // This should not happen.
2055
    return scope.Close(Handle<Array>());
2056
  }
2057
  Local<Array> env = Array::New();
2058
  WCHAR* p = environment;
2059
  int i = 0;
2060
  while (*p != NULL) {
2061
    WCHAR *s;
2062
    if (*p == L'=') {
2063
      // If the key starts with '=' it is a hidden environment variable.
2064
      p += wcslen(p) + 1;
2065
      continue;
2066
    } else {
2067
      s = wcschr(p, L'=');
2068
    }
2069
    if (!s) {
2070
      s = p + wcslen(p);
2071
    }
2072
    env->Set(i++, String::New(reinterpret_cast<uint16_t*>(p), s - p));
2073
    p = s + wcslen(s) + 1;
2074
  }
2075
  FreeEnvironmentStringsW(environment);
2076
#endif
2077
  return scope.Close(env);
2078
}
2079

    
2080

    
2081
static Handle<Object> GetFeatures() {
2082
  HandleScope scope;
2083

    
2084
  Local<Object> obj = Object::New();
2085
  obj->Set(String::NewSymbol("debug"),
2086
#if defined(DEBUG) && DEBUG
2087
    True()
2088
#else
2089
    False()
2090
#endif
2091
  );
2092

    
2093
  obj->Set(String::NewSymbol("uv"), True());
2094
  obj->Set(String::NewSymbol("ipv6"), True()); // TODO ping libuv
2095
  obj->Set(String::NewSymbol("tls_npn"), Boolean::New(use_npn));
2096
  obj->Set(String::NewSymbol("tls_sni"), Boolean::New(use_sni));
2097
  obj->Set(String::NewSymbol("tls"),
2098
      Boolean::New(get_builtin_module("crypto") != NULL));
2099

    
2100
  return scope.Close(obj);
2101
}
2102

    
2103

    
2104
static Handle<Value> DebugPortGetter(Local<String> property,
2105
                                     const AccessorInfo& info) {
2106
  HandleScope scope;
2107
  return scope.Close(Integer::NewFromUnsigned(debug_port));
2108
}
2109

    
2110

    
2111
static void DebugPortSetter(Local<String> property,
2112
                            Local<Value> value,
2113
                            const AccessorInfo& info) {
2114
  HandleScope scope;
2115
  debug_port = value->NumberValue();
2116
}
2117

    
2118

    
2119
static Handle<Value> DebugProcess(const Arguments& args);
2120
static Handle<Value> DebugPause(const Arguments& args);
2121
static Handle<Value> DebugEnd(const Arguments& args);
2122

    
2123
Handle<Object> SetupProcessObject(int argc, char *argv[]) {
2124
  HandleScope scope;
2125

    
2126
  int i, j;
2127

    
2128
  Local<FunctionTemplate> process_template = FunctionTemplate::New();
2129

    
2130
  process = Persistent<Object>::New(process_template->GetFunction()->NewInstance());
2131

    
2132

    
2133
  process->SetAccessor(String::New("title"),
2134
                       ProcessTitleGetter,
2135
                       ProcessTitleSetter);
2136

    
2137
  // process.version
2138
  process->Set(String::NewSymbol("version"), String::New(NODE_VERSION));
2139

    
2140
#ifdef NODE_PREFIX
2141
  // process.installPrefix
2142
  process->Set(String::NewSymbol("installPrefix"), String::New(NODE_PREFIX));
2143
#endif
2144

    
2145
  // process.moduleLoadList
2146
  module_load_list = Persistent<Array>::New(Array::New());
2147
  process->Set(String::NewSymbol("moduleLoadList"), module_load_list);
2148

    
2149
  // process.versions
2150
  Local<Object> versions = Object::New();
2151
  process->Set(String::NewSymbol("versions"), versions);
2152
  versions->Set(String::NewSymbol("http_parser"), String::New(
2153
               NODE_STRINGIFY(HTTP_PARSER_VERSION_MAJOR) "."
2154
               NODE_STRINGIFY(HTTP_PARSER_VERSION_MINOR)));
2155
  // +1 to get rid of the leading 'v'
2156
  versions->Set(String::NewSymbol("node"), String::New(NODE_VERSION+1));
2157
  versions->Set(String::NewSymbol("v8"), String::New(V8::GetVersion()));
2158
  versions->Set(String::NewSymbol("ares"), String::New(ARES_VERSION_STR));
2159
  versions->Set(String::NewSymbol("uv"), String::New(
2160
               NODE_STRINGIFY(UV_VERSION_MAJOR) "."
2161
               NODE_STRINGIFY(UV_VERSION_MINOR)));
2162
  versions->Set(String::NewSymbol("zlib"), String::New(ZLIB_VERSION));
2163
#if HAVE_OPENSSL
2164
  // Stupid code to slice out the version string.
2165
  int c, l = strlen(OPENSSL_VERSION_TEXT);
2166
  for (i = j = 0; i < l; i++) {
2167
    c = OPENSSL_VERSION_TEXT[i];
2168
    if ('0' <= c && c <= '9') {
2169
      for (j = i + 1; j < l; j++) {
2170
        c = OPENSSL_VERSION_TEXT[j];
2171
        if (c == ' ') break;
2172
      }
2173
      break;
2174
    }
2175
  }
2176
  versions->Set(String::NewSymbol("openssl"),
2177
                String::New(OPENSSL_VERSION_TEXT + i, j - i));
2178
#endif
2179

    
2180

    
2181

    
2182
  // process.arch
2183
  process->Set(String::NewSymbol("arch"), String::New(ARCH));
2184

    
2185
  // process.platform
2186
  process->Set(String::NewSymbol("platform"), String::New(PLATFORM));
2187

    
2188
  // process.argv
2189
  Local<Array> arguments = Array::New(argc - option_end_index + 1);
2190
  arguments->Set(Integer::New(0), String::New(argv[0]));
2191
  for (j = 1, i = option_end_index; i < argc; j++, i++) {
2192
    Local<String> arg = String::New(argv[i]);
2193
    arguments->Set(Integer::New(j), arg);
2194
  }
2195
  // assign it
2196
  process->Set(String::NewSymbol("argv"), arguments);
2197

    
2198
  // process.execArgv
2199
  Local<Array> execArgv = Array::New(option_end_index - 1);
2200
  for (j = 1, i = 0; j < option_end_index; j++, i++) {
2201
    execArgv->Set(Integer::New(i), String::New(argv[j]));
2202
  }
2203
  // assign it
2204
  process->Set(String::NewSymbol("execArgv"), execArgv);
2205

    
2206

    
2207
  // create process.env
2208
  Local<ObjectTemplate> envTemplate = ObjectTemplate::New();
2209
  envTemplate->SetNamedPropertyHandler(EnvGetter,
2210
                                       EnvSetter,
2211
                                       EnvQuery,
2212
                                       EnvDeleter,
2213
                                       EnvEnumerator,
2214
                                       Undefined());
2215
  Local<Object> env = envTemplate->NewInstance();
2216
  process->Set(String::NewSymbol("env"), env);
2217

    
2218
  process->Set(String::NewSymbol("pid"), Integer::New(getpid()));
2219
  process->Set(String::NewSymbol("features"), GetFeatures());
2220

    
2221
  // -e, --eval
2222
  if (eval_string) {
2223
    process->Set(String::NewSymbol("_eval"), String::New(eval_string));
2224
  }
2225

    
2226
  // -p, --print
2227
  if (print_eval) {
2228
    process->Set(String::NewSymbol("_print_eval"), True());
2229
  }
2230

    
2231
  // -i, --interactive
2232
  if (force_repl) {
2233
    process->Set(String::NewSymbol("_forceRepl"), True());
2234
  }
2235

    
2236
  size_t size = 2*PATH_MAX;
2237
  char* execPath = new char[size];
2238
  if (uv_exepath(execPath, &size) != 0) {
2239
    // as a last ditch effort, fallback on argv[0] ?
2240
    process->Set(String::NewSymbol("execPath"), String::New(argv[0]));
2241
  } else {
2242
    process->Set(String::NewSymbol("execPath"), String::New(execPath, size));
2243
  }
2244
  delete [] execPath;
2245

    
2246
  process->SetAccessor(String::New("debugPort"),
2247
                       DebugPortGetter,
2248
                       DebugPortSetter);
2249

    
2250

    
2251
  // define various internal methods
2252
  NODE_SET_METHOD(process, "_getActiveRequests", GetActiveRequests);
2253
  NODE_SET_METHOD(process, "_getActiveHandles", GetActiveHandles);
2254
  NODE_SET_METHOD(process, "_needTickCallback", NeedTickCallback);
2255
  NODE_SET_METHOD(process, "reallyExit", Exit);
2256
  NODE_SET_METHOD(process, "abort", Abort);
2257
  NODE_SET_METHOD(process, "chdir", Chdir);
2258
  NODE_SET_METHOD(process, "cwd", Cwd);
2259

    
2260
  NODE_SET_METHOD(process, "umask", Umask);
2261

    
2262
#ifdef __POSIX__
2263
  NODE_SET_METHOD(process, "getuid", GetUid);
2264
  NODE_SET_METHOD(process, "setuid", SetUid);
2265

    
2266
  NODE_SET_METHOD(process, "setgid", SetGid);
2267
  NODE_SET_METHOD(process, "getgid", GetGid);
2268
#endif // __POSIX__
2269

    
2270
  NODE_SET_METHOD(process, "_kill", Kill);
2271

    
2272
  NODE_SET_METHOD(process, "_debugProcess", DebugProcess);
2273
  NODE_SET_METHOD(process, "_debugPause", DebugPause);
2274
  NODE_SET_METHOD(process, "_debugEnd", DebugEnd);
2275

    
2276
  NODE_SET_METHOD(process, "hrtime", Hrtime);
2277

    
2278
  NODE_SET_METHOD(process, "dlopen", DLOpen);
2279

    
2280
  NODE_SET_METHOD(process, "uptime", Uptime);
2281
  NODE_SET_METHOD(process, "memoryUsage", MemoryUsage);
2282
  NODE_SET_METHOD(process, "uvCounters", UVCounters);
2283

    
2284
  NODE_SET_METHOD(process, "binding", Binding);
2285

    
2286
  return process;
2287
}
2288

    
2289

    
2290
static void AtExit() {
2291
  uv_tty_reset_mode();
2292
}
2293

    
2294

    
2295
static void SignalExit(int signal) {
2296
  uv_tty_reset_mode();
2297
  _exit(1);
2298
}
2299

    
2300

    
2301
void Load(Handle<Object> process_l) {
2302
  // Compile, execute the src/node.js file. (Which was included as static C
2303
  // string in node_natives.h. 'natve_node' is the string containing that
2304
  // source code.)
2305

    
2306
  // The node.js file returns a function 'f'
2307
  atexit(AtExit);
2308

    
2309
  TryCatch try_catch;
2310

    
2311
  Local<Value> f_value = ExecuteString(MainSource(),
2312
                                       IMMUTABLE_STRING("node.js"));
2313
  if (try_catch.HasCaught())  {
2314
    ReportException(try_catch, true);
2315
    exit(10);
2316
  }
2317
  assert(f_value->IsFunction());
2318
  Local<Function> f = Local<Function>::Cast(f_value);
2319

    
2320
  // Now we call 'f' with the 'process' variable that we've built up with
2321
  // all our bindings. Inside node.js we'll take care of assigning things to
2322
  // their places.
2323

    
2324
  // We start the process this way in order to be more modular. Developers
2325
  // who do not like how 'src/node.js' setups the module system but do like
2326
  // Node's I/O bindings may want to replace 'f' with their own function.
2327

    
2328
  // Add a reference to the global object
2329
  Local<Object> global = v8::Context::GetCurrent()->Global();
2330
  Local<Value> args[1] = { Local<Value>::New(process_l) };
2331

    
2332
#if defined HAVE_DTRACE || defined HAVE_ETW
2333
  InitDTrace(global);
2334
#endif
2335

    
2336
  f->Call(global, 1, args);
2337

    
2338
  if (try_catch.HasCaught())  {
2339
    ReportException(try_catch, true);
2340
    exit(11);
2341
  }
2342
}
2343

    
2344
static void PrintHelp();
2345

    
2346
static void ParseDebugOpt(const char* arg) {
2347
  const char *p = 0;
2348

    
2349
  use_debug_agent = true;
2350
  if (!strcmp (arg, "--debug-brk")) {
2351
    debug_wait_connect = true;
2352
    return;
2353
  } else if (!strcmp(arg, "--debug")) {
2354
    return;
2355
  } else if (strstr(arg, "--debug-brk=") == arg) {
2356
    debug_wait_connect = true;
2357
    p = 1 + strchr(arg, '=');
2358
    debug_port = atoi(p);
2359
  } else if (strstr(arg, "--debug=") == arg) {
2360
    p = 1 + strchr(arg, '=');
2361
    debug_port = atoi(p);
2362
  }
2363
  if (p && debug_port > 1024 && debug_port <  65536)
2364
      return;
2365

    
2366
  fprintf(stderr, "Bad debug option.\n");
2367
  if (p) fprintf(stderr, "Debug port must be in range 1025 to 65535.\n");
2368

    
2369
  PrintHelp();
2370
  exit(1);
2371
}
2372

    
2373
static void PrintHelp() {
2374
  printf("Usage: node [options] [ -e script | script.js ] [arguments] \n"
2375
         "       node debug script.js [arguments] \n"
2376
         "\n"
2377
         "Options:\n"
2378
         "  -v, --version        print node's version\n"
2379
         "  -e, --eval script    evaluate script\n"
2380
         "  -p, --print          print result of --eval\n"
2381
         "  -i, --interactive    always enter the REPL even if stdin\n"
2382
         "                       does not appear to be a terminal\n"
2383
         "  --v8-options         print v8 command line options\n"
2384
         "  --vars               print various compiled-in variables\n"
2385
         "  --max-stack-size=val set max v8 stack size (bytes)\n"
2386
         "\n"
2387
         "Environment variables:\n"
2388
#ifdef _WIN32
2389
         "NODE_PATH              ';'-separated list of directories\n"
2390
#else
2391
         "NODE_PATH              ':'-separated list of directories\n"
2392
#endif
2393
         "                       prefixed to the module search path.\n"
2394
         "NODE_MODULE_CONTEXTS   Set to 1 to load modules in their own\n"
2395
         "                       global contexts.\n"
2396
         "NODE_DISABLE_COLORS    Set to 1 to disable colors in the REPL\n"
2397
         "\n"
2398
         "Documentation can be found at http://nodejs.org/\n");
2399
}
2400

    
2401
// Parse node command line arguments.
2402
static void ParseArgs(int argc, char **argv) {
2403
  int i;
2404

    
2405
  // TODO use parse opts
2406
  for (i = 1; i < argc; i++) {
2407
    const char *arg = argv[i];
2408
    if (strstr(arg, "--debug") == arg) {
2409
      ParseDebugOpt(arg);
2410
      argv[i] = const_cast<char*>("");
2411
    } else if (strcmp(arg, "--version") == 0 || strcmp(arg, "-v") == 0) {
2412
      printf("%s\n", NODE_VERSION);
2413
      exit(0);
2414
    } else if (strcmp(arg, "--vars") == 0) {
2415
#ifdef NODE_PREFIX
2416
      printf("NODE_PREFIX: %s\n", NODE_PREFIX);
2417
#endif
2418
#ifdef NODE_CFLAGS
2419
      printf("NODE_CFLAGS: %s\n", NODE_CFLAGS);
2420
#endif
2421
      exit(0);
2422
    } else if (strstr(arg, "--max-stack-size=") == arg) {
2423
      const char *p = 0;
2424
      p = 1 + strchr(arg, '=');
2425
      max_stack_size = atoi(p);
2426
      argv[i] = const_cast<char*>("");
2427
    } else if (strcmp(arg, "--help") == 0 || strcmp(arg, "-h") == 0) {
2428
      PrintHelp();
2429
      exit(0);
2430
    } else if (strcmp(arg, "--eval") == 0 || strcmp(arg, "-e") == 0 ||
2431
        strcmp(arg, "-pe") == 0) {
2432
      if (argc <= i + 1) {
2433
        fprintf(stderr, "Error: --eval requires an argument\n");
2434
        exit(1);
2435
      }
2436
      if (arg[1] == 'p') {
2437
        print_eval = true;
2438
      }
2439
      argv[i] = const_cast<char*>("");
2440
      eval_string = argv[++i];
2441
    } else if (strcmp(arg, "--print") == 0 || strcmp(arg, "-p") == 0) {
2442
      print_eval = true;
2443
      argv[i] = const_cast<char*>("");
2444
    } else if (strcmp(arg, "--interactive") == 0 || strcmp(arg, "-i") == 0) {
2445
      force_repl = true;
2446
      argv[i] = const_cast<char*>("");
2447
    } else if (strcmp(arg, "--v8-options") == 0) {
2448
      argv[i] = const_cast<char*>("--help");
2449
    } else if (argv[i][0] != '-') {
2450
      break;
2451
    }
2452
  }
2453

    
2454
  option_end_index = i;
2455
}
2456

    
2457

    
2458
static Isolate* node_isolate = NULL;
2459
static volatile bool debugger_running = false;
2460

    
2461
static void EnableDebug(bool wait_connect) {
2462
  // If we're called from another thread, make sure to enter the right
2463
  // v8 isolate.
2464
  node_isolate->Enter();
2465

    
2466
  // Start the debug thread and it's associated TCP server on port 5858.
2467
  bool r = v8::Debug::EnableAgent("node " NODE_VERSION,
2468
                                  debug_port,
2469
                                  wait_connect);
2470

    
2471
  // Crappy check that everything went well. FIXME
2472
  assert(r);
2473

    
2474
  // Print out some information.
2475
  fprintf(stderr, "debugger listening on port %d\n", debug_port);
2476
  fflush(stderr);
2477

    
2478
  debugger_running = true;
2479

    
2480
  node_isolate->Exit();
2481
}
2482

    
2483

    
2484
#ifdef __POSIX__
2485
static void EnableDebugSignalHandler(int signal) {
2486
  // Break once process will return execution to v8
2487
  v8::Debug::DebugBreak(node_isolate);
2488

    
2489
  if (!debugger_running) {
2490
    fprintf(stderr, "Hit SIGUSR1 - starting debugger agent.\n");
2491
    EnableDebug(false);
2492
  }
2493
}
2494

    
2495

    
2496
static void RegisterSignalHandler(int signal, void (*handler)(int)) {
2497
  struct sigaction sa;
2498

    
2499
  memset(&sa, 0, sizeof(sa));
2500
  sa.sa_handler = handler;
2501
  sigfillset(&sa.sa_mask);
2502
  sigaction(signal, &sa, NULL);
2503
}
2504

    
2505

    
2506
Handle<Value> DebugProcess(const Arguments& args) {
2507
  HandleScope scope;
2508

    
2509
  if (args.Length() != 1) {
2510
    return ThrowException(Exception::Error(
2511
        String::New("Invalid number of arguments.")));
2512
  }
2513

    
2514
  pid_t pid;
2515
  int r;
2516

    
2517
  pid = args[0]->IntegerValue();
2518
  r = kill(pid, SIGUSR1);
2519
  if (r != 0) {
2520
    return ThrowException(ErrnoException(errno, "kill"));
2521
  }
2522

    
2523
  return Undefined();
2524
}
2525
#endif // __POSIX__
2526

    
2527

    
2528
#ifdef _WIN32
2529
DWORD WINAPI EnableDebugThreadProc(void* arg) {
2530
  // Break once process will return execution to v8
2531
  if (!debugger_running) {
2532
    for (int i = 0; i < 1; i++) {
2533
      fprintf(stderr, "Starting debugger agent.\r\n");
2534
      fflush(stderr);
2535
      EnableDebug(false);
2536
    }
2537
  }
2538

    
2539
  v8::Debug::DebugBreak();
2540

    
2541
  return 0;
2542
}
2543

    
2544

    
2545
static int GetDebugSignalHandlerMappingName(DWORD pid, wchar_t* buf,
2546
    size_t buf_len) {
2547
  return _snwprintf(buf, buf_len, L"node-debug-handler-%u", pid);
2548
}
2549

    
2550

    
2551
static int RegisterDebugSignalHandler() {
2552
  wchar_t mapping_name[32];
2553
  HANDLE mapping_handle;
2554
  DWORD pid;
2555
  LPTHREAD_START_ROUTINE* handler;
2556

    
2557
  pid = GetCurrentProcessId();
2558

    
2559
  if (GetDebugSignalHandlerMappingName(pid,
2560
                                       mapping_name,
2561
                                       ARRAY_SIZE(mapping_name)) < 0) {
2562
    return -1;
2563
  }
2564

    
2565
  mapping_handle = CreateFileMappingW(INVALID_HANDLE_VALUE,
2566
                                      NULL,
2567
                                      PAGE_READWRITE,
2568
                                      0,
2569
                                      sizeof *handler,
2570
                                      mapping_name);
2571
  if (mapping_handle == NULL) {
2572
    return -1;
2573
  }
2574

    
2575
  handler = reinterpret_cast<LPTHREAD_START_ROUTINE*>(
2576
      MapViewOfFile(mapping_handle,
2577
                    FILE_MAP_ALL_ACCESS,
2578
                    0,
2579
                    0,
2580
                    sizeof *handler));
2581
  if (handler == NULL) {
2582
    CloseHandle(mapping_handle);
2583
    return -1;
2584
  }
2585

    
2586
  *handler = EnableDebugThreadProc;
2587

    
2588
  UnmapViewOfFile((void*) handler);
2589

    
2590
  return 0;
2591
}
2592

    
2593

    
2594
static Handle<Value> DebugProcess(const Arguments& args) {
2595
  HandleScope scope;
2596
  Handle<Value> rv = Undefined();
2597
  DWORD pid;
2598
  HANDLE process = NULL;
2599
  HANDLE thread = NULL;
2600
  HANDLE mapping = NULL;
2601
  wchar_t mapping_name[32];
2602
  LPTHREAD_START_ROUTINE* handler = NULL;
2603

    
2604
  if (args.Length() != 1) {
2605
    rv = ThrowException(Exception::Error(String::New("Invalid number of arguments.")));
2606
    goto out;
2607
  }
2608

    
2609
  pid = (DWORD) args[0]->IntegerValue();
2610

    
2611
  process = OpenProcess(PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION |
2612
                            PROCESS_VM_OPERATION | PROCESS_VM_WRITE |
2613
                            PROCESS_VM_READ,
2614
                        FALSE,
2615
                        pid);
2616
  if (process == NULL) {
2617
    rv = ThrowException(WinapiErrnoException(GetLastError(), "OpenProcess"));
2618
    goto out;
2619
  }
2620

    
2621
  if (GetDebugSignalHandlerMappingName(pid,
2622
                                       mapping_name,
2623
                                       ARRAY_SIZE(mapping_name)) < 0) {
2624
    rv = ThrowException(ErrnoException(errno, "sprintf"));
2625
    goto out;
2626
  }
2627

    
2628
  mapping = OpenFileMappingW(FILE_MAP_READ, FALSE, mapping_name);
2629
  if (mapping == NULL) {
2630
    rv = ThrowException(WinapiErrnoException(GetLastError(),
2631
                                             "OpenFileMappingW"));
2632
    goto out;
2633
  }
2634

    
2635
  handler = reinterpret_cast<LPTHREAD_START_ROUTINE*>(
2636
      MapViewOfFile(mapping,
2637
                    FILE_MAP_READ,
2638
                    0,
2639
                    0,
2640
                    sizeof *handler));
2641
  if (handler == NULL || *handler == NULL) {
2642
    rv = ThrowException(WinapiErrnoException(GetLastError(), "MapViewOfFile"));
2643
    goto out;
2644
  }
2645

    
2646
  thread = CreateRemoteThread(process,
2647
                              NULL,
2648
                              0,
2649
                              *handler,
2650
                              NULL,
2651
                              0,
2652
                              NULL);
2653
  if (thread == NULL) {
2654
    rv = ThrowException(WinapiErrnoException(GetLastError(),
2655
                                             "CreateRemoteThread"));
2656
    goto out;
2657
  }
2658

    
2659
  // Wait for the thread to terminate
2660
  if (WaitForSingleObject(thread, INFINITE) != WAIT_OBJECT_0) {
2661
    rv = ThrowException(WinapiErrnoException(GetLastError(),
2662
                                             "WaitForSingleObject"));
2663
    goto out;
2664
  }
2665

    
2666
 out:
2667
  if (process != NULL) {
2668
   CloseHandle(process);
2669
  }
2670
  if (thread != NULL) {
2671
    CloseHandle(thread);
2672
  }
2673
  if (handler != NULL) {
2674
    UnmapViewOfFile(handler);
2675
  }
2676
  if (mapping != NULL) {
2677
    CloseHandle(mapping);
2678
  }
2679

    
2680
  return Undefined();
2681
}
2682
#endif // _WIN32
2683

    
2684

    
2685
static Handle<Value> DebugPause(const Arguments& args) {
2686
  v8::Debug::DebugBreak(node_isolate);
2687
  return Undefined();
2688
}
2689

    
2690

    
2691
static Handle<Value> DebugEnd(const Arguments& args) {
2692
  if (debugger_running) {
2693
    v8::Debug::DisableAgent();
2694
    debugger_running = false;
2695
  }
2696

    
2697
  return Undefined();
2698
}
2699

    
2700

    
2701
char** Init(int argc, char *argv[]) {
2702
  // Initialize prog_start_time to get relative uptime.
2703
  uv_uptime(&prog_start_time);
2704

    
2705
  // Parse a few arguments which are specific to Node.
2706
  node::ParseArgs(argc, argv);
2707
  // Parse the rest of the args (up to the 'option_end_index' (where '--' was
2708
  // in the command line))
2709
  int v8argc = option_end_index;
2710
  char **v8argv = argv;
2711

    
2712
  if (debug_wait_connect) {
2713
    // v8argv is a copy of argv up to the script file argument +2 if --debug-brk
2714
    // to expose the v8 debugger js object so that node.js can set
2715
    // a breakpoint on the first line of the startup script
2716
    v8argc += 2;
2717
    v8argv = new char*[v8argc];
2718
    memcpy(v8argv, argv, sizeof(argv) * option_end_index);
2719
    v8argv[option_end_index] = const_cast<char*>("--expose_debug_as");
2720
    v8argv[option_end_index + 1] = const_cast<char*>("v8debug");
2721
  }
2722

    
2723
  // For the normal stack which moves from high to low addresses when frames
2724
  // are pushed, we can compute the limit as stack_size bytes below the
2725
  // the address of a stack variable (e.g. &stack_var) as an approximation
2726
  // of the start of the stack (we're assuming that we haven't pushed a lot
2727
  // of frames yet).
2728
  if (max_stack_size != 0) {
2729
    uint32_t stack_var;
2730
    ResourceConstraints constraints;
2731

    
2732
    uint32_t *stack_limit = &stack_var - (max_stack_size / sizeof(uint32_t));
2733
    constraints.set_stack_limit(stack_limit);
2734
    SetResourceConstraints(&constraints); // Must be done before V8::Initialize
2735
  }
2736
  V8::SetFlagsFromCommandLine(&v8argc, v8argv, false);
2737

    
2738
#ifdef __POSIX__
2739
  // Ignore SIGPIPE
2740
  RegisterSignalHandler(SIGPIPE, SIG_IGN);
2741
  RegisterSignalHandler(SIGINT, SignalExit);
2742
  RegisterSignalHandler(SIGTERM, SignalExit);
2743
#endif // __POSIX__
2744

    
2745
  uv_prepare_init(uv_default_loop(), &prepare_tick_watcher);
2746
  uv_prepare_start(&prepare_tick_watcher, PrepareTick);
2747
  uv_unref(reinterpret_cast<uv_handle_t*>(&prepare_tick_watcher));
2748

    
2749
  uv_check_init(uv_default_loop(), &check_tick_watcher);
2750
  uv_check_start(&check_tick_watcher, node::CheckTick);
2751
  uv_unref(reinterpret_cast<uv_handle_t*>(&check_tick_watcher));
2752

    
2753
  uv_idle_init(uv_default_loop(), &tick_spinner);
2754

    
2755
  uv_check_init(uv_default_loop(), &gc_check);
2756
  uv_check_start(&gc_check, node::Check);
2757
  uv_unref(reinterpret_cast<uv_handle_t*>(&gc_check));
2758

    
2759
  uv_idle_init(uv_default_loop(), &gc_idle);
2760
  uv_unref(reinterpret_cast<uv_handle_t*>(&gc_idle));
2761

    
2762
  uv_timer_init(uv_default_loop(), &gc_timer);
2763
  uv_unref(reinterpret_cast<uv_handle_t*>(&gc_timer));
2764

    
2765
  V8::SetFatalErrorHandler(node::OnFatalError);
2766

    
2767
  // Fetch a reference to the main isolate, so we have a reference to it
2768
  // even when we need it to access it from another (debugger) thread.
2769
  node_isolate = Isolate::GetCurrent();
2770

    
2771
  // If the --debug flag was specified then initialize the debug thread.
2772
  if (use_debug_agent) {
2773
    EnableDebug(debug_wait_connect);
2774
  } else {
2775
#ifdef _WIN32
2776
    RegisterDebugSignalHandler();
2777
#else // Posix
2778
    RegisterSignalHandler(SIGUSR1, EnableDebugSignalHandler);
2779
#endif // __POSIX__
2780
  }
2781

    
2782
  return argv;
2783
}
2784

    
2785

    
2786
struct AtExitCallback {
2787
  AtExitCallback* next_;
2788
  void (*cb_)(void* arg);
2789
  void* arg_;
2790
};
2791

    
2792
static AtExitCallback* at_exit_functions_;
2793

    
2794

    
2795
void RunAtExit() {
2796
  AtExitCallback* p = at_exit_functions_;
2797
  at_exit_functions_ = NULL;
2798

    
2799
  while (p) {
2800
    AtExitCallback* q = p->next_;
2801
    p->cb_(p->arg_);
2802
    delete p;
2803
    p = q;
2804
  }
2805
}
2806

    
2807

    
2808
void AtExit(void (*cb)(void* arg), void* arg) {
2809
  AtExitCallback* p = new AtExitCallback;
2810
  p->cb_ = cb;
2811
  p->arg_ = arg;
2812
  p->next_ = at_exit_functions_;
2813
  at_exit_functions_ = p;
2814
}
2815

    
2816

    
2817
void EmitExit(v8::Handle<v8::Object> process_l) {
2818
  // process.emit('exit')
2819
  process_l->Set(String::NewSymbol("_exiting"), True());
2820
  Local<Value> emit_v = process_l->Get(String::New("emit"));
2821
  assert(emit_v->IsFunction());
2822
  Local<Function> emit = Local<Function>::Cast(emit_v);
2823
  Local<Value> args[] = { String::New("exit"), Integer::New(0) };
2824
  TryCatch try_catch;
2825
  emit->Call(process_l, 2, args);
2826
  if (try_catch.HasCaught()) {
2827
    FatalException(try_catch);
2828
  }
2829
}
2830

    
2831
static char **copy_argv(int argc, char **argv) {
2832
  size_t strlen_sum;
2833
  char **argv_copy;
2834
  char *argv_data;
2835
  size_t len;
2836
  int i;
2837

    
2838
  strlen_sum = 0;
2839
  for(i = 0; i < argc; i++) {
2840
    strlen_sum += strlen(argv[i]) + 1;
2841
  }
2842

    
2843
  argv_copy = (char **) malloc(sizeof(char *) * (argc + 1) + strlen_sum);
2844
  if (!argv_copy) {
2845
    return NULL;
2846
  }
2847

    
2848
  argv_data = (char *) argv_copy + sizeof(char *) * (argc + 1);
2849

    
2850
  for(i = 0; i < argc; i++) {
2851
    argv_copy[i] = argv_data;
2852
    len = strlen(argv[i]) + 1;
2853
    memcpy(argv_data, argv[i], len);
2854
    argv_data += len;
2855
  }
2856

    
2857
  argv_copy[argc] = NULL;
2858

    
2859
  return argv_copy;
2860
}
2861

    
2862
int Start(int argc, char *argv[]) {
2863
  // Hack aroung with the argv pointer. Used for process.title = "blah".
2864
  argv = uv_setup_args(argc, argv);
2865

    
2866
  // Logic to duplicate argv as Init() modifies arguments
2867
  // that are passed into it.
2868
  char **argv_copy = copy_argv(argc, argv);
2869

    
2870
  // This needs to run *before* V8::Initialize()
2871
  // Use copy here as to not modify the original argv:
2872
  Init(argc, argv_copy);
2873

    
2874
  V8::Initialize();
2875
  {
2876
    Locker locker;
2877
    HandleScope handle_scope;
2878

    
2879
    // Create the one and only Context.
2880
    Persistent<Context> context = Context::New();
2881
    Context::Scope context_scope(context);
2882

    
2883
    process_symbol = NODE_PSYMBOL("process");
2884
    domain_symbol = NODE_PSYMBOL("domain");
2885

    
2886
    // Use original argv, as we're just copying values out of it.
2887
    Handle<Object> process_l = SetupProcessObject(argc, argv);
2888
    v8_typed_array::AttachBindings(context->Global());
2889

    
2890
    // Create all the objects, load modules, do everything.
2891
    // so your next reading stop should be node::Load()!
2892
    Load(process_l);
2893

    
2894
    // All our arguments are loaded. We've evaluated all of the scripts. We
2895
    // might even have created TCP servers. Now we enter the main eventloop. If
2896
    // there are no watchers on the loop (except for the ones that were
2897
    // uv_unref'd) then this function exits. As long as there are active
2898
    // watchers, it blocks.
2899
    uv_run(uv_default_loop());
2900

    
2901
#ifdef HAVE_ETW
2902
    shutdown_etw();
2903
#endif
2904

    
2905
    EmitExit(process_l);
2906
    RunAtExit();
2907

    
2908
#ifndef NDEBUG
2909
    context.Dispose();
2910
#endif
2911
  }
2912

    
2913
#ifndef NDEBUG
2914
  // Clean up. Not strictly necessary.
2915
  V8::Dispose();
2916
#endif  // NDEBUG
2917

    
2918
  // Clean up the copy:
2919
  free(argv_copy);
2920

    
2921
  return 0;
2922
}
2923

    
2924

    
2925
}  // namespace node