blob: cb5b25bcc97d45694ab1e61a802dfd5bfed7a786 [file] [log] [blame]
Ryan Dahl55048cd2011-03-10 08:54:521// Copyright Joyent, Inc. and other Node contributors.
2//
3// Permission is hereby granted, free of charge, to any person obtaining a
4// copy of this software and associated documentation files (the
5// "Software"), to deal in the Software without restriction, including
6// without limitation the rights to use, copy, modify, merge, publish,
7// distribute, sublicense, and/or sell copies of the Software, and to permit
8// persons to whom the Software is furnished to do so, subject to the
9// following conditions:
10//
11// The above copyright notice and this permission notice shall be included
12// in all copies or substantial portions of the Software.
13//
14// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
17// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
18// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
20// USE OR OTHER DEALINGS IN THE SOFTWARE.
Bert Beldere0f47be2011-01-17 23:22:3621
Ben Noordhuisff4a9d32012-03-09 23:11:1122#include "node.h"
Ben Noordhuis5f040652012-04-28 16:45:1023#include "req_wrap.h"
24#include "handle_wrap.h"
Ryan63a9cd32009-04-15 08:08:2825
Bert Belder22d03c92012-08-06 23:48:1526#include "ares.h"
Ben Noordhuisff4a9d32012-03-09 23:11:1127#include "uv.h"
Ryan Dahlefca3342011-05-13 02:16:4028
Ben Noordhuisff4a9d32012-03-09 23:11:1129#include "v8-debug.h"
Igor Zinkovsky35a14212012-06-11 23:23:1730#if defined HAVE_DTRACE || defined HAVE_ETW
Ben Noordhuisff4a9d32012-03-09 23:11:1131# include "node_dtrace.h"
Ryan Dahlb3ddb892011-10-26 18:31:1232#endif
Ryan Dahl4635ed72010-03-11 20:40:1933
Bert Beldere0f47be2011-01-17 23:22:3634#include <locale.h>
Bert Belder9cec08e2011-05-23 23:42:2235#include <signal.h>
Ryan19478ed2009-03-03 00:56:1536#include <stdio.h>
Ryan34a6f102009-05-28 12:47:1637#include <stdlib.h>
Ryan Dahlc90e44e2010-05-10 23:38:4738#include <string.h>
Peter Bright13d6a1f2011-08-06 04:23:2539#if !defined(_MSC_VER)
40#include <strings.h>
41#else
42#define strcasecmp _stricmp
43#endif
Ryan82d986d2009-09-02 18:18:5044#include <limits.h> /* PATH_MAX */
Ryan19478ed2009-03-03 00:56:1545#include <assert.h>
Peter Bright13d6a1f2011-08-06 04:23:2546#if !defined(_MSC_VER)
47#include <unistd.h> /* setuid, getuid */
48#else
49#include <direct.h>
Peter Bright13d6a1f2011-08-06 04:23:2550#include <process.h>
51#define getpid _getpid
Peter Brightb9d77772011-08-11 01:45:5652#include <io.h>
53#define umask _umask
54typedef int mode_t;
Peter Bright13d6a1f2011-08-06 04:23:2555#endif
Michael Carter8ea6adc2009-09-01 09:39:3056#include <errno.h>
Michael Cartera3860762010-02-08 06:13:1057#include <sys/types.h>
Nathan Rajlich9701f1c2012-03-08 18:56:5958#include "zlib.h"
Ryane02b71e2009-03-03 23:31:3759
Bert Beldere0f47be2011-01-17 23:22:3660#ifdef __POSIX__
Bert Beldera177d602010-11-25 00:02:5561# include <pwd.h> /* getpwnam() */
62# include <grp.h> /* getgrnam() */
63#endif
64
Ben Noordhuisff4a9d32012-03-09 23:11:1165#include "node_buffer.h"
Ben Noordhuisff4a9d32012-03-09 23:11:1166#include "node_file.h"
67#include "node_http_parser.h"
Ben Noordhuisff4a9d32012-03-09 23:11:1168#include "node_constants.h"
69#include "node_javascript.h"
70#include "node_version.h"
71#include "node_string.h"
Peter Bright13d6a1f2011-08-06 04:23:2572#if HAVE_OPENSSL
Ben Noordhuisff4a9d32012-03-09 23:11:1173# include "node_crypto.h"
Rhys Jonesfb3a9cd2010-04-02 23:11:5374#endif
Ben Noordhuisff4a9d32012-03-09 23:11:1175#include "node_script.h"
76#include "v8_typed_array.h"
Ryan6dd850a2009-09-08 12:59:4377
Ryan19478ed2009-03-03 00:56:1578using namespace v8;
Ryan19478ed2009-03-03 00:56:1579
Rasmus Andersson50443f02010-10-11 15:19:1180# ifdef __APPLE__
81# include <crt_externs.h>
82# define environ (*_NSGetEnviron())
Peter Bright13d6a1f2011-08-06 04:23:2583# elif !defined(_MSC_VER)
Ryan3e4fc9f2009-09-10 14:48:3884extern char **environ;
Rasmus Andersson50443f02010-10-11 15:19:1185# endif
Ryan3e4fc9f2009-09-10 14:48:3886
Ryand6c9d312009-09-11 14:02:2987namespace node {
88
Ben Noordhuis5f040652012-04-28 16:45:1089ngx_queue_t handle_wrap_queue = { &handle_wrap_queue, &handle_wrap_queue };
90ngx_queue_t req_wrap_queue = { &req_wrap_queue, &req_wrap_queue };
91
Ben Noordhuis636add22012-04-27 16:58:3092// declared in req_wrap.h
93Persistent<String> process_symbol;
94Persistent<String> domain_symbol;
Ben Noordhuis809fdf22011-12-09 20:49:1095
Ben Noordhuis74a82152012-02-03 15:32:0096static Persistent<Object> process;
97
98static Persistent<String> errno_symbol;
99static Persistent<String> syscall_symbol;
100static Persistent<String> errpath_symbol;
101static Persistent<String> code_symbol;
102
103static Persistent<String> rss_symbol;
104static Persistent<String> heap_total_symbol;
105static Persistent<String> heap_used_symbol;
106
107static Persistent<String> listeners_symbol;
108static Persistent<String> uncaught_exception_symbol;
109static Persistent<String> emit_symbol;
110
isaacs0109a9f2012-07-17 00:29:06111static Persistent<Function> process_makeCallback;
isaacs10ce3d12012-04-13 23:27:23112
Ben Noordhuis74a82152012-02-03 15:32:00113
114static bool print_eval = false;
Nathan Rajlichfeaa8a42012-03-21 07:05:25115static bool force_repl = false;
isaacs5b399292012-06-21 18:42:33116static bool trace_deprecation = false;
Ben Noordhuis74a82152012-02-03 15:32:00117static char *eval_string = NULL;
118static int option_end_index = 0;
119static bool use_debug_agent = false;
120static bool debug_wait_connect = false;
121static int debug_port=5858;
122static int max_stack_size = 0;
123
isaacs48c3d202012-06-21 19:20:23124// used by C++ modules as well
125bool no_deprecation = false;
126
Ben Noordhuis74a82152012-02-03 15:32:00127static uv_idle_t tick_spinner;
128static bool need_tick_cb;
129static Persistent<String> tick_callback_sym;
130
131
132#ifdef OPENSSL_NPN_NEGOTIATED
133static bool use_npn = true;
134#else
135static bool use_npn = false;
136#endif
137
138#ifdef SSL_CTRL_SET_TLSEXT_SERVERNAME_CB
139static bool use_sni = true;
140#else
141static bool use_sni = false;
142#endif
143
144#ifdef __POSIX__
145// Buffer for getpwnam_r(), getgrpam_r() and other misc callers; keep this
146// scoped at file-level rather than method-level to avoid excess stack usage.
147static char getbuf[PATH_MAX + 1];
148#endif
149
150// We need to notify V8 when we're idle so that it can run the garbage
151// collector. The interface to this is V8::IdleNotification(). It returns
152// true if the heap hasn't be fully compacted, and needs to be run again.
153// Returning false means that it doesn't have anymore work to do.
154//
155// A rather convoluted algorithm has been devised to determine when Node is
156// idle. You'll have to figure it out for yourself.
157static uv_check_t gc_check;
158static uv_idle_t gc_idle;
159static uv_timer_t gc_timer;
160bool need_gc;
161
162// process-relative uptime base, initialized at start-up
163static double prog_start_time;
164
165#define FAST_TICK 700.
166#define GC_WAIT_TIME 5000.
167#define RPM_SAMPLES 100
168#define TICK_TIME(n) tick_times[(tick_time_head - (n)) % RPM_SAMPLES]
169static int64_t tick_times[RPM_SAMPLES];
170static int tick_time_head;
Ben Noordhuis2df81c52011-12-09 17:49:17171
Ryan Dahlf657d582011-06-22 12:06:26172static void CheckStatus(uv_timer_t* watcher, int status);
Ben Noordhuis809fdf22011-12-09 20:49:10173
Ryan Dahl3ac6dee2010-05-08 02:05:59174static void StartGCTimer () {
Ryan Dahl7a5977b2011-06-07 16:37:27175 if (!uv_is_active((uv_handle_t*) &gc_timer)) {
Ryan Dahl7547c7d2011-12-07 01:00:33176 uv_timer_start(&gc_timer, node::CheckStatus, 5000, 5000);
Ryan Dahlac3bc2e2010-04-15 08:29:39177 }
178}
179
Ryan Dahl3ac6dee2010-05-08 02:05:59180static void StopGCTimer () {
Ryan Dahl7a5977b2011-06-07 16:37:27181 if (uv_is_active((uv_handle_t*) &gc_timer)) {
Bert Belder9cec08e2011-05-23 23:42:22182 uv_timer_stop(&gc_timer);
Ryan Dahlac3bc2e2010-04-15 08:29:39183 }
184}
Ryan Dahldaacb812010-02-21 02:23:21185
Ryan Dahlf657d582011-06-22 12:06:26186static void Idle(uv_idle_t* watcher, int status) {
Ryan Dahl7a5977b2011-06-07 16:37:27187 assert((uv_idle_t*) watcher == &gc_idle);
Ryan Dahl801fb8a2010-04-05 20:51:32188
Ryan Dahl801fb8a2010-04-05 20:51:32189 if (V8::IdleNotification()) {
Ryan Dahl7a5977b2011-06-07 16:37:27190 uv_idle_stop(&gc_idle);
Ryan Dahl3ac6dee2010-05-08 02:05:59191 StopGCTimer();
Ryan Dahl801fb8a2010-04-05 20:51:32192 }
Ryan Dahl801fb8a2010-04-05 20:51:32193}
194
195
Ryan Dahl3ac6dee2010-05-08 02:05:59196// Called directly after every call to select() (or epoll, or whatever)
Ryan Dahlf657d582011-06-22 12:06:26197static void Check(uv_check_t* watcher, int status) {
198 assert(watcher == &gc_check);
Ryan Dahl801fb8a2010-04-05 20:51:32199
Ben Noordhuis74a82152012-02-03 15:32:00200 tick_times[tick_time_head] = uv_now(uv_default_loop());
Ryan Dahl3ac6dee2010-05-08 02:05:59201 tick_time_head = (tick_time_head + 1) % RPM_SAMPLES;
Ryan Dahl801fb8a2010-04-05 20:51:32202
Ryan Dahl3ac6dee2010-05-08 02:05:59203 StartGCTimer();
Ryan Dahl801fb8a2010-04-05 20:51:32204
Ryan Dahl3ac6dee2010-05-08 02:05:59205 for (int i = 0; i < (int)(GC_WAIT_TIME/FAST_TICK); i++) {
206 double d = TICK_TIME(i+1) - TICK_TIME(i+2);
207 //printf("d = %f\n", d);
208 // If in the last 5 ticks the difference between
209 // ticks was less than 0.7 seconds, then continue.
210 if (d < FAST_TICK) {
211 //printf("---\n");
212 return;
213 }
Ryan Dahl801fb8a2010-04-05 20:51:32214 }
Ryan Dahl3ac6dee2010-05-08 02:05:59215
216 // Otherwise start the gc!
217
218 //fprintf(stderr, "start idle 2\n");
Ryan Dahl7547c7d2011-12-07 01:00:33219 uv_idle_start(&gc_idle, node::Idle);
Ryan Dahldaacb812010-02-21 02:23:21220}
221
Ryan Dahlf80cc692010-01-06 09:17:58222
Ryan Dahl17f3ffa2010-09-09 17:30:37223static void Tick(void) {
Ryan Dahl4e7e2f82010-04-13 22:39:15224 // Avoid entering a V8 scope.
225 if (!need_tick_cb) return;
Ryan Dahl4e7e2f82010-04-13 22:39:15226 need_tick_cb = false;
Ben Noordhuis039fac62012-05-17 05:13:29227
228 uv_idle_stop(&tick_spinner);
Ryan Dahl4e7e2f82010-04-13 22:39:15229
230 HandleScope scope;
231
232 if (tick_callback_sym.IsEmpty()) {
233 // Lazily set the symbol
isaacsa26bee82012-04-12 23:03:47234 tick_callback_sym = NODE_PSYMBOL("_tickCallback");
Ryan Dahl4e7e2f82010-04-13 22:39:15235 }
236
237 Local<Value> cb_v = process->Get(tick_callback_sym);
238 if (!cb_v->IsFunction()) return;
239 Local<Function> cb = Local<Function>::Cast(cb_v);
240
241 TryCatch try_catch;
242
isaacs430d94e2012-07-17 15:17:34243 // Let the tick callback know that this is coming from the spinner
244 Handle<Value> argv[] = { True() };
245 cb->Call(process, ARRAY_SIZE(argv), argv);
Ryan Dahl4e7e2f82010-04-13 22:39:15246
247 if (try_catch.HasCaught()) {
248 FatalException(try_catch);
249 }
250}
251
252
Ryan Dahlf657d582011-06-22 12:06:26253static void Spin(uv_idle_t* handle, int status) {
Bert Belder09ac99f2011-06-08 01:46:29254 assert((uv_idle_t*) handle == &tick_spinner);
255 assert(status == 0);
256 Tick();
257}
258
Ben Noordhuis59b584c2012-07-26 11:19:14259
Felix Geisendörfer81403332012-05-08 14:07:14260static void StartTickSpinner() {
Bert Belder09ac99f2011-06-08 01:46:29261 need_tick_cb = true;
262 // TODO: this tick_spinner shouldn't be necessary. An ev_prepare should be
263 // sufficent, the problem is only in the case of the very last "tick" -
264 // there is nothing left to do in the event loop and libev will exit. The
265 // ev_prepare callback isn't called before exiting. Thus we start this
266 // tick_spinner to keep the event loop alive long enough to handle it.
Ben Noordhuis039fac62012-05-17 05:13:29267 uv_idle_start(&tick_spinner, Spin);
Bert Belder09ac99f2011-06-08 01:46:29268}
269
Ben Noordhuis59b584c2012-07-26 11:19:14270
Felix Geisendörfer81403332012-05-08 14:07:14271static Handle<Value> NeedTickCallback(const Arguments& args) {
272 StartTickSpinner();
273 return Undefined();
274}
Bert Belder09ac99f2011-06-08 01:46:29275
Ryan Dahl17f3ffa2010-09-09 17:30:37276
Ryan Dahlc9e27b12010-04-23 00:53:45277static inline const char *errno_string(int errorno) {
278#define ERRNO_CASE(e) case e: return #e;
279 switch (errorno) {
280
281#ifdef EACCES
282 ERRNO_CASE(EACCES);
283#endif
284
285#ifdef EADDRINUSE
286 ERRNO_CASE(EADDRINUSE);
287#endif
288
289#ifdef EADDRNOTAVAIL
290 ERRNO_CASE(EADDRNOTAVAIL);
291#endif
292
293#ifdef EAFNOSUPPORT
294 ERRNO_CASE(EAFNOSUPPORT);
295#endif
296
297#ifdef EAGAIN
298 ERRNO_CASE(EAGAIN);
Ryan Dahl9b2aac62010-04-28 19:58:00299#endif
300
301#ifdef EWOULDBLOCK
302# if EAGAIN != EWOULDBLOCK
Ryan Dahlc9e27b12010-04-23 00:53:45303 ERRNO_CASE(EWOULDBLOCK);
304# endif
305#endif
306
307#ifdef EALREADY
308 ERRNO_CASE(EALREADY);
309#endif
310
311#ifdef EBADF
312 ERRNO_CASE(EBADF);
313#endif
314
315#ifdef EBADMSG
316 ERRNO_CASE(EBADMSG);
317#endif
318
319#ifdef EBUSY
320 ERRNO_CASE(EBUSY);
321#endif
322
323#ifdef ECANCELED
324 ERRNO_CASE(ECANCELED);
325#endif
326
327#ifdef ECHILD
328 ERRNO_CASE(ECHILD);
329#endif
330
331#ifdef ECONNABORTED
332 ERRNO_CASE(ECONNABORTED);
333#endif
334
335#ifdef ECONNREFUSED
336 ERRNO_CASE(ECONNREFUSED);
337#endif
338
339#ifdef ECONNRESET
340 ERRNO_CASE(ECONNRESET);
341#endif
342
343#ifdef EDEADLK
344 ERRNO_CASE(EDEADLK);
345#endif
346
347#ifdef EDESTADDRREQ
348 ERRNO_CASE(EDESTADDRREQ);
349#endif
350
351#ifdef EDOM
352 ERRNO_CASE(EDOM);
353#endif
354
355#ifdef EDQUOT
356 ERRNO_CASE(EDQUOT);
357#endif
358
359#ifdef EEXIST
360 ERRNO_CASE(EEXIST);
361#endif
362
363#ifdef EFAULT
364 ERRNO_CASE(EFAULT);
365#endif
366
367#ifdef EFBIG
368 ERRNO_CASE(EFBIG);
369#endif
370
371#ifdef EHOSTUNREACH
372 ERRNO_CASE(EHOSTUNREACH);
373#endif
374
375#ifdef EIDRM
376 ERRNO_CASE(EIDRM);
377#endif
378
379#ifdef EILSEQ
380 ERRNO_CASE(EILSEQ);
381#endif
382
383#ifdef EINPROGRESS
384 ERRNO_CASE(EINPROGRESS);
385#endif
386
387#ifdef EINTR
388 ERRNO_CASE(EINTR);
389#endif
390
391#ifdef EINVAL
392 ERRNO_CASE(EINVAL);
393#endif
394
395#ifdef EIO
396 ERRNO_CASE(EIO);
397#endif
398
399#ifdef EISCONN
400 ERRNO_CASE(EISCONN);
401#endif
402
403#ifdef EISDIR
404 ERRNO_CASE(EISDIR);
405#endif
406
407#ifdef ELOOP
408 ERRNO_CASE(ELOOP);
409#endif
410
411#ifdef EMFILE
412 ERRNO_CASE(EMFILE);
413#endif
414
415#ifdef EMLINK
416 ERRNO_CASE(EMLINK);
417#endif
418
419#ifdef EMSGSIZE
420 ERRNO_CASE(EMSGSIZE);
421#endif
422
423#ifdef EMULTIHOP
424 ERRNO_CASE(EMULTIHOP);
425#endif
426
427#ifdef ENAMETOOLONG
428 ERRNO_CASE(ENAMETOOLONG);
429#endif
430
431#ifdef ENETDOWN
432 ERRNO_CASE(ENETDOWN);
433#endif
434
435#ifdef ENETRESET
436 ERRNO_CASE(ENETRESET);
437#endif
438
439#ifdef ENETUNREACH
440 ERRNO_CASE(ENETUNREACH);
441#endif
442
443#ifdef ENFILE
444 ERRNO_CASE(ENFILE);
445#endif
446
447#ifdef ENOBUFS
448 ERRNO_CASE(ENOBUFS);
449#endif
450
451#ifdef ENODATA
452 ERRNO_CASE(ENODATA);
453#endif
454
455#ifdef ENODEV
456 ERRNO_CASE(ENODEV);
457#endif
458
459#ifdef ENOENT
460 ERRNO_CASE(ENOENT);
461#endif
462
463#ifdef ENOEXEC
464 ERRNO_CASE(ENOEXEC);
465#endif
466
Ryan Dahlc9e27b12010-04-23 00:53:45467#ifdef ENOLINK
468 ERRNO_CASE(ENOLINK);
469#endif
470
Ryan Dahl3bb21b52010-04-28 22:07:15471#ifdef ENOLCK
472# if ENOLINK != ENOLCK
473 ERRNO_CASE(ENOLCK);
474# endif
475#endif
476
Ryan Dahlc9e27b12010-04-23 00:53:45477#ifdef ENOMEM
478 ERRNO_CASE(ENOMEM);
479#endif
480
481#ifdef ENOMSG
482 ERRNO_CASE(ENOMSG);
483#endif
484
485#ifdef ENOPROTOOPT
486 ERRNO_CASE(ENOPROTOOPT);
487#endif
488
489#ifdef ENOSPC
490 ERRNO_CASE(ENOSPC);
491#endif
492
493#ifdef ENOSR
494 ERRNO_CASE(ENOSR);
495#endif
496
497#ifdef ENOSTR
498 ERRNO_CASE(ENOSTR);
499#endif
500
501#ifdef ENOSYS
502 ERRNO_CASE(ENOSYS);
503#endif
504
505#ifdef ENOTCONN
506 ERRNO_CASE(ENOTCONN);
507#endif
508
509#ifdef ENOTDIR
510 ERRNO_CASE(ENOTDIR);
511#endif
512
513#ifdef ENOTEMPTY
514 ERRNO_CASE(ENOTEMPTY);
515#endif
516
517#ifdef ENOTSOCK
518 ERRNO_CASE(ENOTSOCK);
519#endif
520
521#ifdef ENOTSUP
522 ERRNO_CASE(ENOTSUP);
523#else
524# ifdef EOPNOTSUPP
525 ERRNO_CASE(EOPNOTSUPP);
526# endif
527#endif
528
529#ifdef ENOTTY
530 ERRNO_CASE(ENOTTY);
531#endif
532
533#ifdef ENXIO
534 ERRNO_CASE(ENXIO);
535#endif
536
537
538#ifdef EOVERFLOW
539 ERRNO_CASE(EOVERFLOW);
540#endif
541
542#ifdef EPERM
543 ERRNO_CASE(EPERM);
544#endif
545
546#ifdef EPIPE
547 ERRNO_CASE(EPIPE);
548#endif
549
550#ifdef EPROTO
551 ERRNO_CASE(EPROTO);
552#endif
553
554#ifdef EPROTONOSUPPORT
555 ERRNO_CASE(EPROTONOSUPPORT);
556#endif
557
558#ifdef EPROTOTYPE
559 ERRNO_CASE(EPROTOTYPE);
560#endif
561
562#ifdef ERANGE
563 ERRNO_CASE(ERANGE);
564#endif
565
566#ifdef EROFS
567 ERRNO_CASE(EROFS);
568#endif
569
570#ifdef ESPIPE
571 ERRNO_CASE(ESPIPE);
572#endif
573
574#ifdef ESRCH
575 ERRNO_CASE(ESRCH);
576#endif
577
578#ifdef ESTALE
579 ERRNO_CASE(ESTALE);
580#endif
581
582#ifdef ETIME
583 ERRNO_CASE(ETIME);
584#endif
585
586#ifdef ETIMEDOUT
587 ERRNO_CASE(ETIMEDOUT);
588#endif
589
590#ifdef ETXTBSY
591 ERRNO_CASE(ETXTBSY);
592#endif
593
594#ifdef EXDEV
595 ERRNO_CASE(EXDEV);
596#endif
597
598 default: return "";
599 }
600}
601
Felix Geisendörferf8a3cf92010-04-28 13:04:08602const char *signo_string(int signo) {
603#define SIGNO_CASE(e) case e: return #e;
604 switch (signo) {
605
606#ifdef SIGHUP
607 SIGNO_CASE(SIGHUP);
608#endif
609
610#ifdef SIGINT
611 SIGNO_CASE(SIGINT);
612#endif
613
614#ifdef SIGQUIT
615 SIGNO_CASE(SIGQUIT);
616#endif
617
618#ifdef SIGILL
619 SIGNO_CASE(SIGILL);
620#endif
621
622#ifdef SIGTRAP
623 SIGNO_CASE(SIGTRAP);
624#endif
625
626#ifdef SIGABRT
627 SIGNO_CASE(SIGABRT);
628#endif
629
630#ifdef SIGIOT
631# if SIGABRT != SIGIOT
632 SIGNO_CASE(SIGIOT);
633# endif
634#endif
635
636#ifdef SIGBUS
637 SIGNO_CASE(SIGBUS);
638#endif
639
640#ifdef SIGFPE
641 SIGNO_CASE(SIGFPE);
642#endif
643
644#ifdef SIGKILL
645 SIGNO_CASE(SIGKILL);
646#endif
647
648#ifdef SIGUSR1
649 SIGNO_CASE(SIGUSR1);
650#endif
651
652#ifdef SIGSEGV
653 SIGNO_CASE(SIGSEGV);
654#endif
655
656#ifdef SIGUSR2
657 SIGNO_CASE(SIGUSR2);
658#endif
659
660#ifdef SIGPIPE
661 SIGNO_CASE(SIGPIPE);
662#endif
663
664#ifdef SIGALRM
665 SIGNO_CASE(SIGALRM);
666#endif
667
668 SIGNO_CASE(SIGTERM);
Bert Belderdcc35082010-11-25 00:04:31669
670#ifdef SIGCHLD
Felix Geisendörferf8a3cf92010-04-28 13:04:08671 SIGNO_CASE(SIGCHLD);
Bert Belderdcc35082010-11-25 00:04:31672#endif
Felix Geisendörferf8a3cf92010-04-28 13:04:08673
674#ifdef SIGSTKFLT
675 SIGNO_CASE(SIGSTKFLT);
676#endif
677
678
679#ifdef SIGCONT
680 SIGNO_CASE(SIGCONT);
681#endif
682
683#ifdef SIGSTOP
684 SIGNO_CASE(SIGSTOP);
685#endif
686
687#ifdef SIGTSTP
688 SIGNO_CASE(SIGTSTP);
689#endif
690
Bert Belder600a6462012-08-20 21:59:21691#ifdef SIGBREAK
692 SIGNO_CASE(SIGBREAK);
693#endif
694
Felix Geisendörferf8a3cf92010-04-28 13:04:08695#ifdef SIGTTIN
696 SIGNO_CASE(SIGTTIN);
697#endif
698
699#ifdef SIGTTOU
700 SIGNO_CASE(SIGTTOU);
701#endif
702
703#ifdef SIGURG
704 SIGNO_CASE(SIGURG);
705#endif
706
707#ifdef SIGXCPU
708 SIGNO_CASE(SIGXCPU);
709#endif
710
711#ifdef SIGXFSZ
712 SIGNO_CASE(SIGXFSZ);
713#endif
714
715#ifdef SIGVTALRM
716 SIGNO_CASE(SIGVTALRM);
717#endif
718
719#ifdef SIGPROF
720 SIGNO_CASE(SIGPROF);
721#endif
722
723#ifdef SIGWINCH
724 SIGNO_CASE(SIGWINCH);
725#endif
726
727#ifdef SIGIO
728 SIGNO_CASE(SIGIO);
729#endif
730
731#ifdef SIGPOLL
Ryan Dahl3bb21b52010-04-28 22:07:15732# if SIGPOLL != SIGIO
Felix Geisendörferf8a3cf92010-04-28 13:04:08733 SIGNO_CASE(SIGPOLL);
Ryan Dahl3bb21b52010-04-28 22:07:15734# endif
Felix Geisendörferf8a3cf92010-04-28 13:04:08735#endif
736
737#ifdef SIGLOST
738 SIGNO_CASE(SIGLOST);
739#endif
740
741#ifdef SIGPWR
Raffaele Senab3b81d62010-06-09 04:08:05742# if SIGPWR != SIGLOST
Felix Geisendörferf8a3cf92010-04-28 13:04:08743 SIGNO_CASE(SIGPWR);
Raffaele Senab3b81d62010-06-09 04:08:05744# endif
Felix Geisendörferf8a3cf92010-04-28 13:04:08745#endif
746
747#ifdef SIGSYS
748 SIGNO_CASE(SIGSYS);
749#endif
750
Felix Geisendörferf8a3cf92010-04-28 13:04:08751 default: return "";
752 }
753}
754
Ryan Dahlc9e27b12010-04-23 00:53:45755
756Local<Value> ErrnoException(int errorno,
757 const char *syscall,
visionmedia45948e02010-05-14 14:52:49758 const char *msg,
759 const char *path) {
760 Local<Value> e;
Ryan Dahlc9e27b12010-04-23 00:53:45761 Local<String> estring = String::NewSymbol(errno_string(errorno));
Bert Belder2ce09612011-01-17 21:47:59762 if (!msg[0]) {
Bert Belder2ce09612011-01-17 21:47:59763 msg = strerror(errorno);
Bert Belder2ce09612011-01-17 21:47:59764 }
Ryan Dahlc9e27b12010-04-23 00:53:45765 Local<String> message = String::NewSymbol(msg);
766
767 Local<String> cons1 = String::Concat(estring, String::NewSymbol(", "));
768 Local<String> cons2 = String::Concat(cons1, message);
769
Ryan Dahl6cc42922011-10-19 23:53:07770 if (syscall_symbol.IsEmpty()) {
Ryan Dahlc9e27b12010-04-23 00:53:45771 syscall_symbol = NODE_PSYMBOL("syscall");
772 errno_symbol = NODE_PSYMBOL("errno");
visionmedia45948e02010-05-14 14:52:49773 errpath_symbol = NODE_PSYMBOL("path");
Ryan Dahlaa95e572011-02-04 22:35:14774 code_symbol = NODE_PSYMBOL("code");
Ryan Dahlc9e27b12010-04-23 00:53:45775 }
776
visionmedia45948e02010-05-14 14:52:49777 if (path) {
778 Local<String> cons3 = String::Concat(cons2, String::NewSymbol(" '"));
779 Local<String> cons4 = String::Concat(cons3, String::New(path));
780 Local<String> cons5 = String::Concat(cons4, String::NewSymbol("'"));
781 e = Exception::Error(cons5);
782 } else {
783 e = Exception::Error(cons2);
784 }
785
786 Local<Object> obj = e->ToObject();
787
Ryan Dahlc9e27b12010-04-23 00:53:45788 obj->Set(errno_symbol, Integer::New(errorno));
Ryan Dahlaa95e572011-02-04 22:35:14789 obj->Set(code_symbol, estring);
visionmedia45948e02010-05-14 14:52:49790 if (path) obj->Set(errpath_symbol, String::New(path));
Ryan Dahlc9e27b12010-04-23 00:53:45791 if (syscall) obj->Set(syscall_symbol, String::NewSymbol(syscall));
792 return e;
793}
794
795
Bert Belder823a4432011-12-01 23:02:51796static const char* get_uv_errno_string(int errorno) {
797 uv_err_t err;
798 memset(&err, 0, sizeof err);
799 err.code = (uv_err_code)errorno;
800 return uv_err_name(err);
801}
802
803
804static const char* get_uv_errno_message(int errorno) {
805 uv_err_t err;
806 memset(&err, 0, sizeof err);
807 err.code = (uv_err_code)errorno;
808 return uv_strerror(err);
809}
810
811
812// hack alert! copy of ErrnoException, tuned for uv errors
813Local<Value> UVException(int errorno,
814 const char *syscall,
815 const char *msg,
816 const char *path) {
Bert Belder823a4432011-12-01 23:02:51817 if (syscall_symbol.IsEmpty()) {
818 syscall_symbol = NODE_PSYMBOL("syscall");
819 errno_symbol = NODE_PSYMBOL("errno");
820 errpath_symbol = NODE_PSYMBOL("path");
821 code_symbol = NODE_PSYMBOL("code");
822 }
823
824 if (!msg || !msg[0])
825 msg = get_uv_errno_message(errorno);
826
Bert Belder641f2be2011-12-02 01:14:04827 Local<String> estring = String::NewSymbol(get_uv_errno_string(errorno));
Bert Belder823a4432011-12-01 23:02:51828 Local<String> message = String::NewSymbol(msg);
829 Local<String> cons1 = String::Concat(estring, String::NewSymbol(", "));
830 Local<String> cons2 = String::Concat(cons1, message);
831
832 Local<Value> e;
833
834 Local<String> path_str;
835
836 if (path) {
837#ifdef _WIN32
838 if (strncmp(path, "\\\\?\\UNC\\", 8) == 0) {
839 path_str = String::Concat(String::New("\\\\"), String::New(path + 8));
840 } else if (strncmp(path, "\\\\?\\", 4) == 0) {
841 path_str = String::New(path + 4);
842 } else {
843 path_str = String::New(path);
844 }
845#else
846 path_str = String::New(path);
847#endif
848
849 Local<String> cons3 = String::Concat(cons2, String::NewSymbol(" '"));
850 Local<String> cons4 = String::Concat(cons3, path_str);
851 Local<String> cons5 = String::Concat(cons4, String::NewSymbol("'"));
852 e = Exception::Error(cons5);
853 } else {
854 e = Exception::Error(cons2);
855 }
856
857 Local<Object> obj = e->ToObject();
858
859 // TODO errno should probably go
860 obj->Set(errno_symbol, Integer::New(errorno));
861 obj->Set(code_symbol, estring);
862 if (path) obj->Set(errpath_symbol, path_str);
863 if (syscall) obj->Set(syscall_symbol, String::NewSymbol(syscall));
864 return e;
865}
866
867
Bert Belder6ee73a22011-11-04 15:10:48868#ifdef _WIN32
Igor Zinkovsky500c8f42011-12-15 20:36:05869// Does about the same as strerror(),
870// but supports all windows error messages
871static const char *winapi_strerror(const int errorno) {
872 char *errmsg = NULL;
873
874 FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
875 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, errorno,
876 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&errmsg, 0, NULL);
877
878 if (errmsg) {
879 // Remove trailing newlines
880 for (int i = strlen(errmsg) - 1;
881 i >= 0 && (errmsg[i] == '\n' || errmsg[i] == '\r'); i--) {
882 errmsg[i] = '\0';
883 }
884
885 return errmsg;
886 } else {
887 // FormatMessage failed
888 return "Unknown error";
889 }
890}
891
892
Bert Belder6ee73a22011-11-04 15:10:48893Local<Value> WinapiErrnoException(int errorno,
Bert Belder829735e2011-11-04 15:23:02894 const char* syscall,
895 const char* msg,
896 const char* path) {
Bert Belder6ee73a22011-11-04 15:10:48897 Local<Value> e;
Bert Belder829735e2011-11-04 15:23:02898 if (!msg || !msg[0]) {
Bert Belder6ee73a22011-11-04 15:10:48899 msg = winapi_strerror(errorno);
900 }
901 Local<String> message = String::NewSymbol(msg);
902
903 if (syscall_symbol.IsEmpty()) {
904 syscall_symbol = NODE_PSYMBOL("syscall");
905 errno_symbol = NODE_PSYMBOL("errno");
906 errpath_symbol = NODE_PSYMBOL("path");
907 code_symbol = NODE_PSYMBOL("code");
908 }
909
910 if (path) {
911 Local<String> cons1 = String::Concat(message, String::NewSymbol(" '"));
912 Local<String> cons2 = String::Concat(cons1, String::New(path));
913 Local<String> cons3 = String::Concat(cons2, String::NewSymbol("'"));
914 e = Exception::Error(cons3);
915 } else {
916 e = Exception::Error(message);
917 }
918
919 Local<Object> obj = e->ToObject();
920
921 obj->Set(errno_symbol, Integer::New(errorno));
922 if (path) obj->Set(errpath_symbol, String::New(path));
923 if (syscall) obj->Set(syscall_symbol, String::NewSymbol(syscall));
924 return e;
925}
926#endif
927
928
Ben Noordhuis55c65cc2010-09-24 15:02:08929Handle<Value> FromConstructorTemplate(Persistent<FunctionTemplate>& t,
930 const Arguments& args) {
931 HandleScope scope;
932
933 const int argc = args.Length();
Ryan Dahl5dd08c62010-10-09 21:21:26934 Local<Value>* argv = new Local<Value>[argc];
Ben Noordhuis55c65cc2010-09-24 15:02:08935
936 for (int i = 0; i < argc; ++i) {
937 argv[i] = args[i];
938 }
939
940 Local<Object> instance = t->GetFunction()->NewInstance(argc, argv);
Ryan Dahl5dd08c62010-10-09 21:21:26941
942 delete[] argv;
943
Ben Noordhuis55c65cc2010-09-24 15:02:08944 return scope.Close(instance);
945}
946
947
Ryan Dahl650a3082011-05-28 20:44:03948// MakeCallback may only be made directly off the event loop.
949// That is there can be no JavaScript stack frames underneath it.
950// (Is there any way to assert that?)
951//
952// Maybe make this a method of a node::Handle super class
953//
isaacsac1aadd2012-04-13 23:34:48954Handle<Value>
isaacs7407be82012-04-13 23:33:09955MakeCallback(const Handle<Object> object,
956 const char* method,
957 int argc,
958 Handle<Value> argv[]) {
959 HandleScope scope;
isaacsa26bee82012-04-12 23:03:47960
961 Handle<Value> ret =
962 MakeCallback(object, String::NewSymbol(method), argc, argv);
963
964 return scope.Close(ret);
isaacs7407be82012-04-13 23:33:09965}
966
isaacsac1aadd2012-04-13 23:34:48967Handle<Value>
isaacs7407be82012-04-13 23:33:09968MakeCallback(const Handle<Object> object,
969 const Handle<String> symbol,
970 int argc,
971 Handle<Value> argv[]) {
Ryan Dahl650a3082011-05-28 20:44:03972 HandleScope scope;
973
isaacs7407be82012-04-13 23:33:09974 Local<Value> callback_v = object->Get(symbol);
Ryan Dahl26c59052011-10-07 07:57:37975 if (!callback_v->IsFunction()) {
isaacs7407be82012-04-13 23:33:09976 String::Utf8Value method(symbol);
isaacs88f94fa2012-04-17 04:27:12977 // XXX: If the object has a domain attached, handle it there?
978 // At least, would be good to get *some* sort of indication
979 // of how we got here, even if it's not catchable.
980 fprintf(stderr, "Non-function in MakeCallback. method = %s\n", *method);
981 abort();
Ryan Dahl26c59052011-10-07 07:57:37982 }
isaacs88f94fa2012-04-17 04:27:12983
Ryan Dahl650a3082011-05-28 20:44:03984 Local<Function> callback = Local<Function>::Cast(callback_v);
985
isaacsac1aadd2012-04-13 23:34:48986 return scope.Close(MakeCallback(object, callback, argc, argv));
isaacs7407be82012-04-13 23:33:09987}
988
isaacsac1aadd2012-04-13 23:34:48989Handle<Value>
isaacs7407be82012-04-13 23:33:09990MakeCallback(const Handle<Object> object,
991 const Handle<Function> callback,
992 int argc,
993 Handle<Value> argv[]) {
994 HandleScope scope;
995
Ryan Dahl650a3082011-05-28 20:44:03996 // TODO Hook for long stack traces to be made here.
997
998 TryCatch try_catch;
999
isaacs0109a9f2012-07-17 00:29:061000 if (process_makeCallback.IsEmpty()) {
1001 Local<Value> cb_v = process->Get(String::New("_makeCallback"));
1002 if (!cb_v->IsFunction()) {
1003 fprintf(stderr, "process._makeCallback assigned to non-function\n");
1004 abort();
isaacs10ce3d12012-04-13 23:27:231005 }
isaacs0109a9f2012-07-17 00:29:061006 Local<Function> cb = cb_v.As<Function>();
1007 process_makeCallback = Persistent<Function>::New(cb);
isaacs10ce3d12012-04-13 23:27:231008 }
1009
isaacs0109a9f2012-07-17 00:29:061010 Local<Array> argArray = Array::New(argc);
1011 for (int i = 0; i < argc; i++) {
1012 argArray->Set(Integer::New(i), argv[i]);
isaacs10ce3d12012-04-13 23:27:231013 }
1014
isaacs0109a9f2012-07-17 00:29:061015 Local<Value> object_l = Local<Value>::New(object);
1016 Local<Value> callback_l = Local<Value>::New(callback);
Ryan Dahl650a3082011-05-28 20:44:031017
isaacs0109a9f2012-07-17 00:29:061018 Local<Value> args[3] = { object_l, callback_l, argArray };
isaacs10ce3d12012-04-13 23:27:231019
isaacs0109a9f2012-07-17 00:29:061020 Local<Value> ret = process_makeCallback->Call(process, ARRAY_SIZE(args), args);
isaacs10ce3d12012-04-13 23:27:231021
1022 if (try_catch.HasCaught()) {
1023 FatalException(try_catch);
1024 return Undefined();
Ryan Dahl650a3082011-05-28 20:44:031025 }
isaacsac1aadd2012-04-13 23:34:481026
1027 return scope.Close(ret);
Ryan Dahl650a3082011-05-28 20:44:031028}
1029
1030
Ryan Dahl6cc42922011-10-19 23:53:071031void SetErrno(uv_err_t err) {
1032 HandleScope scope;
1033
1034 if (errno_symbol.IsEmpty()) {
1035 errno_symbol = NODE_PSYMBOL("errno");
1036 }
1037
1038 if (err.code == UV_UNKNOWN) {
1039 char errno_buf[100];
1040 snprintf(errno_buf, 100, "Unknown system errno %d", err.sys_errno_);
1041 Context::GetCurrent()->Global()->Set(errno_symbol, String::New(errno_buf));
1042 } else {
1043 Context::GetCurrent()->Global()->Set(errno_symbol,
1044 String::NewSymbol(uv_err_name(err)));
1045 }
Ryan Dahl650a3082011-05-28 20:44:031046}
1047
1048
Ryan Dahl07792af2009-09-21 10:27:221049enum encoding ParseEncoding(Handle<Value> encoding_v, enum encoding _default) {
1050 HandleScope scope;
1051
1052 if (!encoding_v->IsString()) return _default;
1053
ssuda249c3c12012-03-21 16:47:161054 String::Utf8Value encoding(encoding_v);
Ryan Dahl07792af2009-09-21 10:27:221055
1056 if (strcasecmp(*encoding, "utf8") == 0) {
1057 return UTF8;
Ryan Dahl2b994d92009-10-06 08:45:181058 } else if (strcasecmp(*encoding, "utf-8") == 0) {
1059 return UTF8;
Ryan Dahl07792af2009-09-21 10:27:221060 } else if (strcasecmp(*encoding, "ascii") == 0) {
1061 return ASCII;
Ben Noordhuis95638c92010-07-28 12:20:231062 } else if (strcasecmp(*encoding, "base64") == 0) {
1063 return BASE64;
Konstantin Käfer9e101f22011-02-06 20:49:521064 } else if (strcasecmp(*encoding, "ucs2") == 0) {
1065 return UCS2;
1066 } else if (strcasecmp(*encoding, "ucs-2") == 0) {
1067 return UCS2;
Ryan Dahl07792af2009-09-21 10:27:221068 } else if (strcasecmp(*encoding, "binary") == 0) {
1069 return BINARY;
isaacs0aa1a8a2011-02-20 01:29:011070 } else if (strcasecmp(*encoding, "hex") == 0) {
1071 return HEX;
Ryan Dahl07792af2009-09-21 10:27:221072 } else if (strcasecmp(*encoding, "raw") == 0) {
isaacs5b399292012-06-21 18:42:331073 if (!no_deprecation) {
1074 fprintf(stderr, "'raw' (array of integers) has been removed. "
1075 "Use 'binary'.\n");
1076 }
Ryan Dahl07792af2009-09-21 10:27:221077 return BINARY;
1078 } else if (strcasecmp(*encoding, "raws") == 0) {
isaacs5b399292012-06-21 18:42:331079 if (!no_deprecation) {
1080 fprintf(stderr, "'raws' encoding has been renamed to 'binary'. "
1081 "Please update your code.\n");
1082 }
Ryan Dahl07792af2009-09-21 10:27:221083 return BINARY;
1084 } else {
1085 return _default;
1086 }
1087}
1088
Ryand6c9d312009-09-11 14:02:291089Local<Value> Encode(const void *buf, size_t len, enum encoding encoding) {
Ryan21a1b042009-09-09 13:51:491090 HandleScope scope;
1091
Ryan Dahl46ebaa02010-02-22 20:07:071092 if (!len) return scope.Close(String::Empty());
Ryan21a1b042009-09-09 13:51:491093
Ryan Dahl07792af2009-09-21 10:27:221094 if (encoding == BINARY) {
Ryan88900702009-09-09 15:22:201095 const unsigned char *cbuf = static_cast<const unsigned char*>(buf);
Ryand6c9d312009-09-11 14:02:291096 uint16_t * twobytebuf = new uint16_t[len];
Ryan88900702009-09-09 15:22:201097 for (size_t i = 0; i < len; i++) {
Ryand6c9d312009-09-11 14:02:291098 // XXX is the following line platform independent?
Ryan88900702009-09-09 15:22:201099 twobytebuf[i] = cbuf[i];
1100 }
1101 Local<String> chunk = String::New(twobytebuf, len);
Ryan Dahl663deb32009-09-22 16:35:151102 delete [] twobytebuf; // TODO use ExternalTwoByteString?
Ryan88900702009-09-09 15:22:201103 return scope.Close(chunk);
1104 }
1105
Ryan21a1b042009-09-09 13:51:491106 // utf8 or ascii encoding
1107 Local<String> chunk = String::New((const char*)buf, len);
1108 return scope.Close(chunk);
1109}
1110
Ryand6c9d312009-09-11 14:02:291111// Returns -1 if the handle was not valid for decoding
1112ssize_t DecodeBytes(v8::Handle<v8::Value> val, enum encoding encoding) {
Ryan21a1b042009-09-09 13:51:491113 HandleScope scope;
1114
1115 if (val->IsArray()) {
isaacsa3753b42012-05-16 23:32:371116 fprintf(stderr, "'raw' encoding (array of integers) has been removed. "
1117 "Use 'binary'.\n");
Ryan Dahl07792af2009-09-21 10:27:221118 assert(0);
1119 return -1;
Ryan21a1b042009-09-09 13:51:491120 }
1121
Ben Noordhuis9a79bb62012-01-08 23:45:191122 if (encoding == BINARY && Buffer::HasInstance(val)) {
1123 return Buffer::Length(val->ToObject());
1124 }
1125
Ryan Dahl07792af2009-09-21 10:27:221126 Local<String> str = val->ToString();
Ryan21a1b042009-09-09 13:51:491127
Ryand6c9d312009-09-11 14:02:291128 if (encoding == UTF8) return str->Utf8Length();
Konstantin Käfer9e101f22011-02-06 20:49:521129 else if (encoding == UCS2) return str->Length() * 2;
isaacs0aa1a8a2011-02-20 01:29:011130 else if (encoding == HEX) return str->Length() / 2;
Ryan21a1b042009-09-09 13:51:491131
Ryand6c9d312009-09-11 14:02:291132 return str->Length();
Ryan21a1b042009-09-09 13:51:491133}
1134
1135#ifndef MIN
Ryand6c9d312009-09-11 14:02:291136# define MIN(a, b) ((a) < (b) ? (a) : (b))
Ryan21a1b042009-09-09 13:51:491137#endif
1138
1139// Returns number of bytes written.
Ryan Dahl53530e92010-04-02 21:55:281140ssize_t DecodeWrite(char *buf,
1141 size_t buflen,
Ryand6c9d312009-09-11 14:02:291142 v8::Handle<v8::Value> val,
1143 enum encoding encoding) {
Ryan21a1b042009-09-09 13:51:491144 HandleScope scope;
1145
1146 // XXX
1147 // A lot of improvement can be made here. See:
1148 // http://code.google.com/p/v8/issues/detail?id=270
1149 // http://groups.google.com/group/v8-dev/browse_thread/thread/dba28a81d9215291/ece2b50a3b4022c
1150 // http://groups.google.com/group/v8-users/browse_thread/thread/1f83b0ba1f0a611
1151
1152 if (val->IsArray()) {
isaacsa3753b42012-05-16 23:32:371153 fprintf(stderr, "'raw' encoding (array of integers) has been removed. "
1154 "Use 'binary'.\n");
Ryan Dahl07792af2009-09-21 10:27:221155 assert(0);
1156 return -1;
Ryan21a1b042009-09-09 13:51:491157 }
1158
Ben Noordhuis786e1e82012-08-14 20:25:521159 bool is_buffer = Buffer::HasInstance(val);
1160
1161 if (is_buffer && encoding == BINARY) { // fast path, copy buffer data
1162 const char* data = Buffer::Data(val.As<Object>());
1163 size_t size = Buffer::Length(val.As<Object>());
1164 size_t len = size < buflen ? size : buflen;
1165 memcpy(buf, data, len);
1166 return len;
1167 }
1168
1169 Local<String> str;
1170
1171 if (is_buffer) { // slow path, convert to binary string
1172 Local<Value> arg = String::New("binary");
1173 str = MakeCallback(val.As<Object>(), "toString", 1, &arg)->ToString();
1174 }
1175 else {
1176 str = val->ToString();
1177 }
Ryan21a1b042009-09-09 13:51:491178
1179 if (encoding == UTF8) {
Ryan Dahl41ef1712010-04-14 17:34:171180 str->WriteUtf8(buf, buflen, NULL, String::HINT_MANY_WRITES_EXPECTED);
Ryan21a1b042009-09-09 13:51:491181 return buflen;
1182 }
1183
Ryan88900702009-09-09 15:22:201184 if (encoding == ASCII) {
Ryan Dahl41ef1712010-04-14 17:34:171185 str->WriteAscii(buf, 0, buflen, String::HINT_MANY_WRITES_EXPECTED);
Ryan88900702009-09-09 15:22:201186 return buflen;
1187 }
1188
1189 // THIS IS AWFUL!!! FIXME
1190
Ryan Dahl07792af2009-09-21 10:27:221191 assert(encoding == BINARY);
1192
Ryand6c9d312009-09-11 14:02:291193 uint16_t * twobytebuf = new uint16_t[buflen];
Ryan88900702009-09-09 15:22:201194
Ryan Dahl41ef1712010-04-14 17:34:171195 str->Write(twobytebuf, 0, buflen, String::HINT_MANY_WRITES_EXPECTED);
Ryan88900702009-09-09 15:22:201196
1197 for (size_t i = 0; i < buflen; i++) {
1198 unsigned char *b = reinterpret_cast<unsigned char*>(&twobytebuf[i]);
Ryan88900702009-09-09 15:22:201199 buf[i] = b[0];
1200 }
1201
Ryan Dahl663deb32009-09-22 16:35:151202 delete [] twobytebuf;
Ryand6c9d312009-09-11 14:02:291203
Ryan21a1b042009-09-09 13:51:491204 return buflen;
1205}
1206
Ryan Dahlb57c1f52010-11-24 02:46:131207void DisplayExceptionLine (TryCatch &try_catch) {
isaacsb3cf3f32012-07-28 21:00:271208 // Prevent re-entry into this function. For example, if there is
1209 // a throw from a program in vm.runInThisContext(code, filename, true),
1210 // then we want to show the original failure, not the secondary one.
1211 static bool displayed_error = false;
1212
1213 if (displayed_error) return;
1214 displayed_error = true;
1215
Ryan Dahlb57c1f52010-11-24 02:46:131216 HandleScope scope;
1217
Ryan Dahlb20c3432010-02-12 05:55:081218 Handle<Message> message = try_catch.Message();
Ryan Dahlef300d12009-09-13 15:43:191219
Ryan Dahlcdf5d912011-10-11 20:41:331220 uv_tty_reset_mode();
1221
Ryan Dahlb3c03592010-07-27 02:08:211222 fprintf(stderr, "\n");
Ryan Dahl41f213b2010-05-31 18:50:351223
Ryan Dahlb57c1f52010-11-24 02:46:131224 if (!message.IsEmpty()) {
Ryan Dahl53a841d2009-12-29 19:20:511225 // Print (filename):(line number): (message).
1226 String::Utf8Value filename(message->GetScriptResourceName());
Ryan Dahlb57c1f52010-11-24 02:46:131227 const char* filename_string = *filename;
Ryan Dahl53a841d2009-12-29 19:20:511228 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());
Ryan Dahlb57c1f52010-11-24 02:46:131232 const char* sourceline_string = *sourceline;
Ryan Dahlab068db2010-05-09 20:54:581233
isaacsb3cf3f32012-07-28 21:00:271234 // Because of how node modules work, all scripts are wrapped with a
1235 // "function (module, exports, __filename, ...) {"
Ryan Dahlab068db2010-05-09 20:54:581236 // to provide script local variables.
1237 //
1238 // When reporting errors on the first line of a script, this wrapper
isaacsb3cf3f32012-07-28 21:00:271239 // function is leaked to the user. There used to be a hack here to
1240 // truncate off the first 62 characters, but it caused numerous other
1241 // problems when vm.runIn*Context() methods were used for non-module
1242 // code.
Ryan Dahlab068db2010-05-09 20:54:581243 //
isaacsb3cf3f32012-07-28 21:00:271244 // If we ever decide to re-instate such a hack, the following steps
1245 // must be taken:
Ryan Dahlab068db2010-05-09 20:54:581246 //
isaacsb3cf3f32012-07-28 21:00:271247 // 1. Pass a flag around to say "this code was wrapped"
1248 // 2. Update the stack frame output so that it is also correct.
1249 //
1250 // It would probably be simpler to add a line rather than add some
1251 // number of characters to the first line, since V8 truncates the
1252 // sourceline to 78 characters, and we end up not providing very much
1253 // useful debugging info to the user if we remove 62 characters.
Ryan Dahlab068db2010-05-09 20:54:581254
Ryan Dahl53a841d2009-12-29 19:20:511255 int start = message->GetStartColumn();
isaacsb3cf3f32012-07-28 21:00:271256 int end = message->GetEndColumn();
1257
1258 // fprintf(stderr, "---\nsourceline:%s\noffset:%d\nstart:%d\nend:%d\n---\n", sourceline_string, start, end);
1259
1260 fprintf(stderr, "%s\n", sourceline_string);
1261 // Print wavy underline (GetUnderline is deprecated).
1262 for (int i = 0; i < start; i++) {
Oleg Efimov968b49b2012-05-21 15:27:151263 fputc((sourceline_string[i] == '\t') ? '\t' : ' ', stderr);
Ryan Dahl53a841d2009-12-29 19:20:511264 }
Ryan Dahl53a841d2009-12-29 19:20:511265 for (int i = start; i < end; i++) {
Oleg Efimov968b49b2012-05-21 15:27:151266 fputc('^', stderr);
Ryan Dahl53a841d2009-12-29 19:20:511267 }
Oleg Efimov968b49b2012-05-21 15:27:151268 fputc('\n', stderr);
Ryan Dahl8e6dd522010-01-15 18:45:041269 }
Ryan Dahlb57c1f52010-11-24 02:46:131270}
1271
1272
1273static void ReportException(TryCatch &try_catch, bool show_line) {
1274 HandleScope scope;
Ryan Dahlb57c1f52010-11-24 02:46:131275
1276 if (show_line) DisplayExceptionLine(try_catch);
Ryan Dahl53a841d2009-12-29 19:20:511277
Ryan Dahlda932302010-05-14 18:48:141278 String::Utf8Value trace(try_catch.StackTrace());
1279
isaacs8df6f9e2011-04-25 19:22:181280 // range errors have a trace member set to undefined
1281 if (trace.length() > 0 && !try_catch.StackTrace()->IsUndefined()) {
Ryanafd9e712009-08-31 16:22:091282 fprintf(stderr, "%s\n", *trace);
isaacse9b6b0b2010-10-02 06:22:341283 } else {
1284 // this really only happens for RangeErrors, since they're the only
isaacs8df6f9e2011-04-25 19:22:181285 // kind that won't have all this info in the trace, or when non-Error
1286 // objects are thrown manually.
isaacse9b6b0b2010-10-02 06:22:341287 Local<Value> er = try_catch.Exception();
isaacs8df6f9e2011-04-25 19:22:181288 bool isErrorObject = er->IsObject() &&
1289 !(er->ToObject()->Get(String::New("message"))->IsUndefined()) &&
1290 !(er->ToObject()->Get(String::New("name"))->IsUndefined());
1291
1292 if (isErrorObject) {
1293 String::Utf8Value name(er->ToObject()->Get(String::New("name")));
1294 fprintf(stderr, "%s: ", *name);
1295 }
1296
ssuda249c3c12012-03-21 16:47:161297 String::Utf8Value msg(!isErrorObject ? er
1298 : er->ToObject()->Get(String::New("message")));
isaacse9b6b0b2010-10-02 06:22:341299 fprintf(stderr, "%s\n", *msg);
Ryan5131e0a2009-03-09 00:23:411300 }
isaacse9b6b0b2010-10-02 06:22:341301
Ryand7e220c2009-09-09 20:35:401302 fflush(stderr);
Ryan5131e0a2009-03-09 00:23:411303}
1304
Ryand6c9d312009-09-11 14:02:291305// Executes a str within the current v8 context.
Tom Hughes74954ce2011-03-08 06:00:511306Local<Value> ExecuteString(Handle<String> source, Handle<Value> filename) {
Ryan63a9cd32009-04-15 08:08:281307 HandleScope scope;
Ryan408526a2009-04-21 11:52:211308 TryCatch try_catch;
1309
Herbert Vojcikc2a06722010-04-17 15:18:151310 Local<v8::Script> script = v8::Script::Compile(source, filename);
Ryan63a9cd32009-04-15 08:08:281311 if (script.IsEmpty()) {
Ryan Dahlab068db2010-05-09 20:54:581312 ReportException(try_catch, true);
Ryan34a6f102009-05-28 12:47:161313 exit(1);
Ryan63a9cd32009-04-15 08:08:281314 }
1315
Ryan Dahl9f5643f2010-01-31 07:22:341316 Local<Value> result = script->Run();
Ryan63a9cd32009-04-15 08:08:281317 if (result.IsEmpty()) {
Ryan Dahlab068db2010-05-09 20:54:581318 ReportException(try_catch, true);
Ryan34a6f102009-05-28 12:47:161319 exit(1);
Ryan63a9cd32009-04-15 08:08:281320 }
1321
1322 return scope.Close(result);
1323}
1324
Felix Geisendörfer7371fcb2009-11-11 17:10:581325
Ben Noordhuis5f040652012-04-28 16:45:101326static Handle<Value> GetActiveRequests(const Arguments& args) {
1327 HandleScope scope;
1328
1329 Local<Array> ary = Array::New();
1330 ngx_queue_t* q = NULL;
1331 int i = 0;
1332
1333 ngx_queue_foreach(q, &req_wrap_queue) {
1334 ReqWrap<uv_req_t>* w = container_of(q, ReqWrap<uv_req_t>, req_wrap_queue_);
1335 if (w->object_.IsEmpty()) continue;
1336 ary->Set(i++, w->object_);
1337 }
1338
1339 return scope.Close(ary);
1340}
1341
1342
1343// Non-static, friend of HandleWrap. Could have been a HandleWrap method but
1344// implemented here for consistency with GetActiveRequests().
1345Handle<Value> GetActiveHandles(const Arguments& args) {
1346 HandleScope scope;
1347
1348 Local<Array> ary = Array::New();
1349 ngx_queue_t* q = NULL;
1350 int i = 0;
1351
Ben Noordhuise813e342012-05-15 15:24:061352 Local<String> owner_sym = String::New("owner");
1353
Ben Noordhuis5f040652012-04-28 16:45:101354 ngx_queue_foreach(q, &handle_wrap_queue) {
1355 HandleWrap* w = container_of(q, HandleWrap, handle_wrap_queue_);
Ben Noordhuis039fac62012-05-17 05:13:291356 if (w->object_.IsEmpty() || w->unref_) continue;
Ben Noordhuise813e342012-05-15 15:24:061357 Local<Value> obj = w->object_->Get(owner_sym);
1358 if (obj->IsUndefined()) obj = *w->object_;
1359 ary->Set(i++, obj);
Ben Noordhuis5f040652012-04-28 16:45:101360 }
1361
1362 return scope.Close(ary);
1363}
1364
1365
Robert Mustacchi22404862011-12-15 01:02:151366static Handle<Value> Abort(const Arguments& args) {
1367 abort();
Igor Zinkovsky88cc6882011-12-16 01:18:281368 return Undefined();
Robert Mustacchi22404862011-12-15 01:02:151369}
1370
1371
Brandon Beacher47fcf782009-11-03 18:13:381372static Handle<Value> Chdir(const Arguments& args) {
1373 HandleScope scope;
Ryan Dahlb20c3432010-02-12 05:55:081374
Brandon Beacher47fcf782009-11-03 18:13:381375 if (args.Length() != 1 || !args[0]->IsString()) {
1376 return ThrowException(Exception::Error(String::New("Bad argument.")));
1377 }
Ryan Dahlb20c3432010-02-12 05:55:081378
ssuda249c3c12012-03-21 16:47:161379 String::Utf8Value path(args[0]);
Ryan Dahlb20c3432010-02-12 05:55:081380
Bert Beldere84edd22011-12-01 23:24:441381 uv_err_t r = uv_chdir(*path);
Ryan Dahlb20c3432010-02-12 05:55:081382
Bert Beldere84edd22011-12-01 23:24:441383 if (r.code != UV_OK) {
1384 return ThrowException(UVException(r.code, "uv_chdir"));
Brandon Beacher47fcf782009-11-03 18:13:381385 }
1386
1387 return Undefined();
1388}
1389
Bert Beldercbcf4fe2011-11-24 01:19:541390
Ryand6c9d312009-09-11 14:02:291391static Handle<Value> Cwd(const Arguments& args) {
Michael Carter8ea6adc2009-09-01 09:39:301392 HandleScope scope;
Bert Beldere84edd22011-12-01 23:24:441393#ifdef _WIN32
1394 /* MAX_PATH is in characters, not bytes. Make sure we have enough headroom. */
1395 char buf[MAX_PATH * 4 + 1];
1396#else
1397 char buf[PATH_MAX + 1];
1398#endif
Michael Carter8ea6adc2009-09-01 09:39:301399
Bert Beldere84edd22011-12-01 23:24:441400 uv_err_t r = uv_cwd(buf, ARRAY_SIZE(buf) - 1);
1401 if (r.code != UV_OK) {
1402 return ThrowException(UVException(r.code, "uv_cwd"));
Michael Carter8ea6adc2009-09-01 09:39:301403 }
Peter Griess4e3c5d82010-07-12 15:47:451404
Bert Beldere84edd22011-12-01 23:24:441405 buf[ARRAY_SIZE(buf) - 1] = '\0';
1406 Local<String> cwd = String::New(buf);
Michael Carter8ea6adc2009-09-01 09:39:301407
1408 return scope.Close(cwd);
1409}
1410
Bert Beldere84edd22011-12-01 23:24:441411
Ryan Dahlacc120a2011-08-09 20:53:561412static Handle<Value> Umask(const Arguments& args) {
Friedemann Altrock0433d822009-11-22 18:52:521413 HandleScope scope;
Rasmus Andersson374300c2010-02-27 17:18:411414 unsigned int old;
isaacs5f2e9092011-01-25 18:40:121415
Ryan Dahlacc120a2011-08-09 20:53:561416 if (args.Length() < 1 || args[0]->IsUndefined()) {
Rasmus Andersson374300c2010-02-27 17:18:411417 old = umask(0);
1418 umask((mode_t)old);
isaacs5f2e9092011-01-25 18:40:121419
1420 } else if(!args[0]->IsInt32() && !args[0]->IsString()) {
Friedemann Altrock0433d822009-11-22 18:52:521421 return ThrowException(Exception::TypeError(
isaacs5f2e9092011-01-25 18:40:121422 String::New("argument must be an integer or octal string.")));
1423
1424 } else {
1425 int oct;
1426 if(args[0]->IsInt32()) {
1427 oct = args[0]->Uint32Value();
1428 } else {
1429 oct = 0;
1430 String::Utf8Value str(args[0]);
1431
1432 // Parse the octal string.
1433 for (int i = 0; i < str.length(); i++) {
1434 char c = (*str)[i];
1435 if (c > '7' || c < '0') {
1436 return ThrowException(Exception::TypeError(
1437 String::New("invalid octal string")));
1438 }
1439 oct *= 8;
1440 oct += c - '0';
1441 }
1442 }
1443 old = umask(static_cast<mode_t>(oct));
Friedemann Altrock0433d822009-11-22 18:52:521444 }
isaacs5f2e9092011-01-25 18:40:121445
Friedemann Altrock0433d822009-11-22 18:52:521446 return scope.Close(Uint32::New(old));
1447}
1448
Michael Cartera3860762010-02-08 06:13:101449
Ryan Dahlacc120a2011-08-09 20:53:561450#ifdef __POSIX__
1451
Michael Cartera3860762010-02-08 06:13:101452static Handle<Value> GetUid(const Arguments& args) {
1453 HandleScope scope;
1454 int uid = getuid();
1455 return scope.Close(Integer::New(uid));
1456}
1457
Ryan Dahlacc120a2011-08-09 20:53:561458
James Duncandf1c1e52010-02-23 22:45:021459static Handle<Value> GetGid(const Arguments& args) {
1460 HandleScope scope;
1461 int gid = getgid();
1462 return scope.Close(Integer::New(gid));
1463}
1464
1465
1466static Handle<Value> SetGid(const Arguments& args) {
1467 HandleScope scope;
Ryan Dahl39943402010-03-15 19:49:401468
James Duncandf1c1e52010-02-23 22:45:021469 if (args.Length() < 1) {
1470 return ThrowException(Exception::Error(
Ryan Dahl39943402010-03-15 19:49:401471 String::New("setgid requires 1 argument")));
James Duncandf1c1e52010-02-23 22:45:021472 }
1473
Peter Griess2420f072010-05-19 00:40:441474 int gid;
Blake Mizerany8c853402010-06-30 06:12:461475
Peter Griess2420f072010-05-19 00:40:441476 if (args[0]->IsNumber()) {
1477 gid = args[0]->Int32Value();
1478 } else if (args[0]->IsString()) {
ssuda249c3c12012-03-21 16:47:161479 String::Utf8Value grpnam(args[0]);
Peter Griess2420f072010-05-19 00:40:441480 struct group grp, *grpp = NULL;
1481 int err;
1482
Peter Griess4e3c5d82010-07-12 15:47:451483 if ((err = getgrnam_r(*grpnam, &grp, getbuf, ARRAY_SIZE(getbuf), &grpp)) ||
Peter Griess2420f072010-05-19 00:40:441484 grpp == NULL) {
Brian White52b9ede2011-03-18 05:39:391485 if (errno == 0)
1486 return ThrowException(Exception::Error(
1487 String::New("setgid group id does not exist")));
1488 else
1489 return ThrowException(ErrnoException(errno, "getgrnam_r"));
Peter Griess2420f072010-05-19 00:40:441490 }
1491
1492 gid = grpp->gr_gid;
1493 } else {
1494 return ThrowException(Exception::Error(
1495 String::New("setgid argument must be a number or a string")));
1496 }
1497
James Duncandf1c1e52010-02-23 22:45:021498 int result;
isaacs0dba38e2010-03-03 09:11:471499 if ((result = setgid(gid)) != 0) {
Peter Griess2420f072010-05-19 00:40:441500 return ThrowException(ErrnoException(errno, "setgid"));
James Duncandf1c1e52010-02-23 22:45:021501 }
1502 return Undefined();
1503}
Michael Cartera3860762010-02-08 06:13:101504
Ryan Dahlacc120a2011-08-09 20:53:561505
Michael Cartera3860762010-02-08 06:13:101506static Handle<Value> SetUid(const Arguments& args) {
1507 HandleScope scope;
1508
1509 if (args.Length() < 1) {
1510 return ThrowException(Exception::Error(
1511 String::New("setuid requires 1 argument")));
1512 }
1513
Peter Griess2420f072010-05-19 00:40:441514 int uid;
1515
1516 if (args[0]->IsNumber()) {
1517 uid = args[0]->Int32Value();
1518 } else if (args[0]->IsString()) {
ssuda249c3c12012-03-21 16:47:161519 String::Utf8Value pwnam(args[0]);
Peter Griess2420f072010-05-19 00:40:441520 struct passwd pwd, *pwdp = NULL;
1521 int err;
1522
Peter Griess4e3c5d82010-07-12 15:47:451523 if ((err = getpwnam_r(*pwnam, &pwd, getbuf, ARRAY_SIZE(getbuf), &pwdp)) ||
Peter Griess2420f072010-05-19 00:40:441524 pwdp == NULL) {
Brian White52b9ede2011-03-18 05:39:391525 if (errno == 0)
1526 return ThrowException(Exception::Error(
1527 String::New("setuid user id does not exist")));
1528 else
1529 return ThrowException(ErrnoException(errno, "getpwnam_r"));
Peter Griess2420f072010-05-19 00:40:441530 }
1531
1532 uid = pwdp->pw_uid;
1533 } else {
1534 return ThrowException(Exception::Error(
1535 String::New("setuid argument must be a number or a string")));
1536 }
1537
Michael Cartera3860762010-02-08 06:13:101538 int result;
1539 if ((result = setuid(uid)) != 0) {
Peter Griess2420f072010-05-19 00:40:441540 return ThrowException(ErrnoException(errno, "setuid"));
Michael Cartera3860762010-02-08 06:13:101541 }
1542 return Undefined();
1543}
1544
Ryan Dahlacc120a2011-08-09 20:53:561545
Bert Belder30bab522010-11-25 00:09:061546#endif // __POSIX__
1547
Michael Cartera3860762010-02-08 06:13:101548
Ryand6c9d312009-09-11 14:02:291549v8::Handle<v8::Value> Exit(const v8::Arguments& args) {
Ryan Dahl6f92d8f2010-02-08 05:59:561550 HandleScope scope;
Ryan Dahl6f92d8f2010-02-08 05:59:561551 exit(args[0]->IntegerValue());
Ryan116f4de2009-08-26 20:03:191552 return Undefined();
Ryan0f517032009-04-29 09:09:321553}
1554
Ryan Dahl3ac6dee2010-05-08 02:05:591555
Ryan Dahlf657d582011-06-22 12:06:261556static void CheckStatus(uv_timer_t* watcher, int status) {
1557 assert(watcher == &gc_timer);
Ryan Dahl3ac6dee2010-05-08 02:05:591558
Ryan Dahl3ac6dee2010-05-08 02:05:591559 // check memory
Ryan Dahl7a5977b2011-06-07 16:37:271560 if (!uv_is_active((uv_handle_t*) &gc_idle)) {
Ryan Dahlaeed9662011-03-18 18:39:441561 HeapStatistics stats;
1562 V8::GetHeapStatistics(&stats);
1563 if (stats.total_heap_size() > 1024 * 1024 * 128) {
Ryan Dahl3ac6dee2010-05-08 02:05:591564 // larger than 128 megs, just start the idle watcher
Ryan Dahl7547c7d2011-12-07 01:00:331565 uv_idle_start(&gc_idle, node::Idle);
Ryan Dahl3ac6dee2010-05-08 02:05:591566 return;
1567 }
1568 }
Ryan Dahl3ac6dee2010-05-08 02:05:591569
Ben Noordhuis74a82152012-02-03 15:32:001570 double d = uv_now(uv_default_loop()) - TICK_TIME(3);
Ryan Dahl3ac6dee2010-05-08 02:05:591571
1572 //printfb("timer d = %f\n", d);
1573
1574 if (d >= GC_WAIT_TIME - 1.) {
1575 //fprintf(stderr, "start idle\n");
Ryan Dahl7547c7d2011-12-07 01:00:331576 uv_idle_start(&gc_idle, node::Idle);
Ryan Dahl3ac6dee2010-05-08 02:05:591577 }
1578}
1579
Igor Zinkovsky500c8f42011-12-15 20:36:051580
Tom Hughescf78ce52011-03-04 23:57:541581static Handle<Value> Uptime(const Arguments& args) {
1582 HandleScope scope;
Igor Zinkovsky500c8f42011-12-15 20:36:051583 double uptime;
Tom Hughescf78ce52011-03-04 23:57:541584
Igor Zinkovsky500c8f42011-12-15 20:36:051585 uv_err_t err = uv_uptime(&uptime);
Tom Hughescf78ce52011-03-04 23:57:541586
Igor Zinkovsky500c8f42011-12-15 20:36:051587 if (err.code != UV_OK) {
Tom Hughescf78ce52011-03-04 23:57:541588 return Undefined();
1589 }
1590
Igor Zinkovsky500c8f42011-12-15 20:36:051591 return scope.Close(Number::New(uptime - prog_start_time));
Tom Hughescf78ce52011-03-04 23:57:541592}
Ryan Dahl3ac6dee2010-05-08 02:05:591593
Ryan Dahlc344fbc2011-10-06 21:59:381594
Ryan Dahlb3b3cfe2009-11-03 12:00:421595v8::Handle<v8::Value> MemoryUsage(const v8::Arguments& args) {
1596 HandleScope scope;
1597
Ryan Dahl5783a522011-10-18 21:30:311598 size_t rss;
Ryan Dahlb3b3cfe2009-11-03 12:00:421599
Igor Zinkovsky500c8f42011-12-15 20:36:051600 uv_err_t err = uv_resident_set_memory(&rss);
Ryan Dahlb3b3cfe2009-11-03 12:00:421601
Igor Zinkovsky500c8f42011-12-15 20:36:051602 if (err.code != UV_OK) {
1603 return ThrowException(UVException(err.code, "uv_resident_set_memory"));
Ryan Dahl3a701292009-11-03 00:30:011604 }
1605
Ryan Dahl3a701292009-11-03 00:30:011606 Local<Object> info = Object::New();
1607
Ryan Dahl45a806a2009-12-09 08:02:211608 if (rss_symbol.IsEmpty()) {
1609 rss_symbol = NODE_PSYMBOL("rss");
Ryan Dahl45a806a2009-12-09 08:02:211610 heap_total_symbol = NODE_PSYMBOL("heapTotal");
1611 heap_used_symbol = NODE_PSYMBOL("heapUsed");
1612 }
1613
Russ Bradberry754e23d2011-11-29 22:28:221614 info->Set(rss_symbol, Number::New(rss));
Ryan Dahl3a701292009-11-03 00:30:011615
Ryan Dahl38e425d2009-11-28 15:31:291616 // V8 memory usage
1617 HeapStatistics v8_heap_stats;
1618 V8::GetHeapStatistics(&v8_heap_stats);
Ryan Dahl45a806a2009-12-09 08:02:211619 info->Set(heap_total_symbol,
Ryan Dahl38e425d2009-11-28 15:31:291620 Integer::NewFromUnsigned(v8_heap_stats.total_heap_size()));
Ryan Dahl45a806a2009-12-09 08:02:211621 info->Set(heap_used_symbol,
Ryan Dahl38e425d2009-11-28 15:31:291622 Integer::NewFromUnsigned(v8_heap_stats.used_heap_size()));
1623
Ryan Dahl3a701292009-11-03 00:30:011624 return scope.Close(info);
1625}
Ryan Dahlb3b3cfe2009-11-03 12:00:421626
Bert Belder4a2cb072010-11-29 17:40:141627
Ryan Dahl6eca9482010-09-17 06:13:031628Handle<Value> Kill(const Arguments& args) {
Brandon Beacher334d56d2009-10-14 21:56:121629 HandleScope scope;
Ryan Dahlb20c3432010-02-12 05:55:081630
Ryan Dahl4227e9d2010-12-21 23:40:101631 if (args.Length() != 2) {
Brandon Beacher334d56d2009-10-14 21:56:121632 return ThrowException(Exception::Error(String::New("Bad argument.")));
1633 }
Ryan Dahlb20c3432010-02-12 05:55:081634
Igor Zinkovsky24a69d22011-11-02 22:06:481635 int pid = args[0]->IntegerValue();
Ryan Dahl6eca9482010-09-17 06:13:031636 int sig = args[1]->Int32Value();
Igor Zinkovsky24a69d22011-11-02 22:06:481637 uv_err_t err = uv_kill(pid, sig);
Brandon Beacher334d56d2009-10-14 21:56:121638
Igor Zinkovsky24a69d22011-11-02 22:06:481639 if (err.code != UV_OK) {
1640 SetErrno(err);
1641 return scope.Close(Integer::New(-1));
1642 }
Brandon Beacher334d56d2009-10-14 21:56:121643
1644 return Undefined();
1645}
1646
Nathan Rajlich07c886f2012-03-05 16:51:581647// used in Hrtime() below
1648#define NANOS_PER_SEC 1000000000
1649
1650// Hrtime exposes libuv's uv_hrtime() high-resolution timer.
1651// The value returned by uv_hrtime() is a 64-bit int representing nanoseconds,
1652// so this function instead returns an Array with 2 entries representing seconds
1653// and nanoseconds, to avoid any integer overflow possibility.
1654// Pass in an Array from a previous hrtime() call to instead get a time diff.
1655Handle<Value> Hrtime(const v8::Arguments& args) {
1656 HandleScope scope;
1657
1658 uint64_t t = uv_hrtime();
1659
1660 if (args.Length() > 0) {
1661 // return a time diff tuple
Nathan Rajlichd3d83d72012-07-08 02:57:021662 if (!args[0]->IsArray()) {
1663 Local<Value> exception = Exception::TypeError(
1664 String::New("process.hrtime() only accepts an Array tuple."));
1665 return ThrowException(exception);
1666 }
Nathan Rajlich07c886f2012-03-05 16:51:581667 Local<Array> inArray = Local<Array>::Cast(args[0]);
1668 uint64_t seconds = inArray->Get(0)->Uint32Value();
1669 uint64_t nanos = inArray->Get(1)->Uint32Value();
1670 t -= (seconds * NANOS_PER_SEC) + nanos;
1671 }
1672
1673 Local<Array> tuple = Array::New(2);
1674 tuple->Set(0, Integer::NewFromUnsigned(t / NANOS_PER_SEC));
1675 tuple->Set(1, Integer::NewFromUnsigned(t % NANOS_PER_SEC));
1676
1677 return scope.Close(tuple);
1678}
1679
Bert Belderdd93c532011-10-28 10:05:091680
1681typedef void (UV_DYNAMIC* extInit)(Handle<Object> exports);
Ryan2b6d7242009-06-20 13:07:101682
Ryan Dahl38814552009-10-09 15:15:471683// DLOpen is node.dlopen(). Used to load 'module.node' dynamically shared
1684// objects.
Ryand6c9d312009-09-11 14:02:291685Handle<Value> DLOpen(const v8::Arguments& args) {
Ryan2b6d7242009-06-20 13:07:101686 HandleScope scope;
Bert Belderdd93c532011-10-28 10:05:091687 char symbol[1024], *base, *pos;
1688 uv_lib_t lib;
Bert Belderdd93c532011-10-28 10:05:091689 int r;
Ryan2b6d7242009-06-20 13:07:101690
Bert Belderdd93c532011-10-28 10:05:091691 if (args.Length() < 2) {
Bert Belder35f41822011-11-04 15:11:391692 Local<Value> exception = Exception::Error(
1693 String::New("process.dlopen takes exactly 2 arguments."));
1694 return ThrowException(exception);
Bert Belderdd93c532011-10-28 10:05:091695 }
Ryana97dce72009-08-31 09:14:341696
ssuda249c3c12012-03-21 16:47:161697 String::Utf8Value filename(args[0]); // Cast
Ryan Dahl38814552009-10-09 15:15:471698 Local<Object> target = args[1]->ToObject(); // Cast
Ryan2b6d7242009-06-20 13:07:101699
Ben Noordhuis039fac62012-05-17 05:13:291700 if (uv_dlopen(*filename, &lib)) {
1701 Local<String> errmsg = String::New(uv_dlerror(&lib));
1702#ifdef _WIN32
1703 // Windows needs to add the filename into the error message
1704 errmsg = String::Concat(errmsg, args[0]->ToString());
Shigeki Ohtsu59c39232012-02-26 12:26:091705#endif
Ben Noordhuis039fac62012-05-17 05:13:291706 return ThrowException(Exception::Error(errmsg));
Ryan2b6d7242009-06-20 13:07:101707 }
1708
ssuda249c3c12012-03-21 16:47:161709 String::Utf8Value path(args[0]);
Bert Belderdd93c532011-10-28 10:05:091710 base = *path;
Paul Querna367b87d2010-07-13 08:33:511711
Bert Belderdd93c532011-10-28 10:05:091712 /* Find the shared library filename within the full path. */
1713#ifdef __POSIX__
1714 pos = strrchr(base, '/');
1715 if (pos != NULL) {
Ben Noordhuisa1fa3ef2011-10-30 16:33:421716 base = pos + 1;
Bert Belderdd93c532011-10-28 10:05:091717 }
1718#else // Windows
1719 for (;;) {
1720 pos = strpbrk(base, "\\/:");
1721 if (pos == NULL) {
1722 break;
Paul Querna367b87d2010-07-13 08:33:511723 }
Bert Belderdd93c532011-10-28 10:05:091724 base = pos + 1;
1725 }
1726#endif
Paul Querna367b87d2010-07-13 08:33:511727
Bert Belderdd93c532011-10-28 10:05:091728 /* Strip the .node extension. */
1729 pos = strrchr(base, '.');
1730 if (pos != NULL) {
1731 *pos = '\0';
1732 }
1733
1734 /* Add the `_module` suffix to the extension name. */
1735 r = snprintf(symbol, sizeof symbol, "%s_module", base);
Ben Noordhuis8c97ad42012-03-30 12:41:431736 if (r <= 0 || static_cast<size_t>(r) >= sizeof symbol) {
Bert Belder35f41822011-11-04 15:11:391737 Local<Value> exception =
1738 Exception::Error(String::New("Out of memory."));
1739 return ThrowException(exception);
Paul Querna367b87d2010-07-13 08:33:511740 }
1741
Bert Belderdd93c532011-10-28 10:05:091742 node_module_struct *mod;
Ben Noordhuis039fac62012-05-17 05:13:291743 if (uv_dlsym(&lib, symbol, reinterpret_cast<void**>(&mod))) {
Ben Noordhuisf6923472012-07-26 23:06:121744 char errmsg[1024];
1745 snprintf(errmsg, sizeof(errmsg), "Symbol %s not found.", symbol);
1746 return ThrowError(errmsg);
Paul Querna367b87d2010-07-13 08:33:511747 }
1748
1749 if (mod->version != NODE_MODULE_VERSION) {
Ben Noordhuisf6923472012-07-26 23:06:121750 char errmsg[1024];
1751 snprintf(errmsg,
1752 sizeof(errmsg),
1753 "Module version mismatch. Expected %d, got %d.",
1754 NODE_MODULE_VERSION, mod->version);
1755 return ThrowError(errmsg);
Ryan2b6d7242009-06-20 13:07:101756 }
Ryan2b6d7242009-06-20 13:07:101757
Ryan Dahl38814552009-10-09 15:15:471758 // Execute the C++ module
Paul Querna367b87d2010-07-13 08:33:511759 mod->register_func(target);
Ryan2b6d7242009-06-20 13:07:101760
Peter Griess4e3c5d82010-07-12 15:47:451761 // Tell coverity that 'handle' should not be freed when we return.
1762 // coverity[leaked_storage]
Ryan2b6d7242009-06-20 13:07:101763 return Undefined();
1764}
1765
Tim-Smartae10a482010-03-12 08:36:001766
Ryand6c9d312009-09-11 14:02:291767static void OnFatalError(const char* location, const char* message) {
Ryan Dahl53a841d2009-12-29 19:20:511768 if (location) {
1769 fprintf(stderr, "FATAL ERROR: %s %s\n", location, message);
1770 } else {
1771 fprintf(stderr, "FATAL ERROR: %s\n", message);
1772 }
Ryan34a6f102009-05-28 12:47:161773 exit(1);
Ryan63a9cd32009-04-15 08:08:281774}
1775
Ryand6c9d312009-09-11 14:02:291776void FatalException(TryCatch &try_catch) {
Felix Geisendörfer2b252ac2009-11-14 22:07:541777 HandleScope scope;
1778
Ryan Dahl45a806a2009-12-09 08:02:211779 if (listeners_symbol.IsEmpty()) {
1780 listeners_symbol = NODE_PSYMBOL("listeners");
1781 uncaught_exception_symbol = NODE_PSYMBOL("uncaughtException");
1782 emit_symbol = NODE_PSYMBOL("emit");
1783 }
1784
1785 Local<Value> listeners_v = process->Get(listeners_symbol);
Felix Geisendörfer2b252ac2009-11-14 22:07:541786 assert(listeners_v->IsFunction());
1787
1788 Local<Function> listeners = Local<Function>::Cast(listeners_v);
1789
Ryan Dahl45a806a2009-12-09 08:02:211790 Local<String> uncaught_exception_symbol_l = Local<String>::New(uncaught_exception_symbol);
1791 Local<Value> argv[1] = { uncaught_exception_symbol_l };
Felix Geisendörfer2b252ac2009-11-14 22:07:541792 Local<Value> ret = listeners->Call(process, 1, argv);
1793
1794 assert(ret->IsArray());
1795
1796 Local<Array> listener_array = Local<Array>::Cast(ret);
1797
1798 uint32_t length = listener_array->Length();
1799 // Report and exit if process has no "uncaughtException" listener
1800 if (length == 0) {
Ryan Dahlab068db2010-05-09 20:54:581801 ReportException(try_catch, true);
Felix Geisendörfer2b252ac2009-11-14 22:07:541802 exit(1);
1803 }
1804
1805 // Otherwise fire the process "uncaughtException" event
Ryan Dahl45a806a2009-12-09 08:02:211806 Local<Value> emit_v = process->Get(emit_symbol);
Felix Geisendörfer2b252ac2009-11-14 22:07:541807 assert(emit_v->IsFunction());
1808
1809 Local<Function> emit = Local<Function>::Cast(emit_v);
1810
1811 Local<Value> error = try_catch.Exception();
Ryan Dahl45a806a2009-12-09 08:02:211812 Local<Value> event_argv[2] = { uncaught_exception_symbol_l, error };
Felix Geisendörfer2b252ac2009-11-14 22:07:541813
isaacs80a55e92012-04-07 02:23:161814 TryCatch event_try_catch;
Felix Geisendörfer2b252ac2009-11-14 22:07:541815 emit->Call(process, 2, event_argv);
isaacs07be9fc2012-05-09 22:12:131816
isaacs80a55e92012-04-07 02:23:161817 if (event_try_catch.HasCaught()) {
1818 // the uncaught exception event threw, so we must exit.
1819 ReportException(event_try_catch, true);
1820 exit(1);
1821 }
Ryane78917b2009-03-09 13:08:311822}
1823
Ryan0e9e9272009-04-04 14:53:431824
Ben Noordhuis74a82152012-02-03 15:32:001825Persistent<Object> binding_cache;
1826Persistent<Array> module_load_list;
1827
Ryan Dahl627fb5a2010-03-15 20:48:031828static Handle<Value> Binding(const Arguments& args) {
1829 HandleScope scope;
1830
1831 Local<String> module = args[0]->ToString();
1832 String::Utf8Value module_v(module);
Paul Querna30dadfc2010-07-14 06:22:411833 node_module_struct* modp;
Ryan Dahl627fb5a2010-03-15 20:48:031834
1835 if (binding_cache.IsEmpty()) {
1836 binding_cache = Persistent<Object>::New(Object::New());
1837 }
1838
1839 Local<Object> exports;
1840
Paul Querna30dadfc2010-07-14 06:22:411841 if (binding_cache->Has(module)) {
1842 exports = binding_cache->Get(module)->ToObject();
Ryan Dahlea9ee1f2011-07-28 02:30:321843 return scope.Close(exports);
1844 }
Ryan Dahl6eca9482010-09-17 06:13:031845
Ryan Dahlea9ee1f2011-07-28 02:30:321846 // Append a string to process.moduleLoadList
1847 char buf[1024];
1848 snprintf(buf, 1024, "Binding %s", *module_v);
1849 uint32_t l = module_load_list->Length();
1850 module_load_list->Set(l, String::New(buf));
1851
1852 if ((modp = get_builtin_module(*module_v)) != NULL) {
Paul Querna30dadfc2010-07-14 06:22:411853 exports = Object::New();
1854 modp->register_func(exports);
1855 binding_cache->Set(module, exports);
Ryan Dahl6eca9482010-09-17 06:13:031856
1857 } else if (!strcmp(*module_v, "constants")) {
1858 exports = Object::New();
1859 DefineConstants(exports);
1860 binding_cache->Set(module, exports);
1861
Ryan Dahlc90546f2010-03-15 21:22:501862 } else if (!strcmp(*module_v, "natives")) {
Paul Querna8dbfe5e2010-07-14 06:32:381863 exports = Object::New();
Ryan Dahlc4636a52010-10-12 18:49:411864 DefineJavaScript(exports);
Paul Querna8dbfe5e2010-07-14 06:32:381865 binding_cache->Set(module, exports);
Ryan Dahlc4636a52010-10-12 18:49:411866
Ryan Dahl627fb5a2010-03-15 20:48:031867 } else {
Ryan Dahl6eca9482010-09-17 06:13:031868
Ryan Dahl627fb5a2010-03-15 20:48:031869 return ThrowException(Exception::Error(String::New("No such module")));
1870 }
1871
1872 return scope.Close(exports);
1873}
1874
Ryan Dahle742d072009-10-09 11:25:041875
Ryan Dahl5185c152010-06-18 07:26:491876static Handle<Value> ProcessTitleGetter(Local<String> property,
1877 const AccessorInfo& info) {
1878 HandleScope scope;
Igor Zinkovsky500c8f42011-12-15 20:36:051879 char buffer[512];
1880 uv_get_process_title(buffer, sizeof(buffer));
1881 return scope.Close(String::New(buffer));
Ryan Dahl5185c152010-06-18 07:26:491882}
1883
1884
1885static void ProcessTitleSetter(Local<String> property,
1886 Local<Value> value,
1887 const AccessorInfo& info) {
1888 HandleScope scope;
ssuda249c3c12012-03-21 16:47:161889 String::Utf8Value title(value);
Igor Zinkovsky500c8f42011-12-15 20:36:051890 // TODO: protect with a lock
1891 uv_set_process_title(*title);
Ryan Dahl5185c152010-06-18 07:26:491892}
1893
1894
Ben Noordhuisb4def482010-10-15 13:48:341895static Handle<Value> EnvGetter(Local<String> property,
1896 const AccessorInfo& info) {
Bert Belder077f9d72012-02-15 22:34:181897 HandleScope scope;
1898#ifdef __POSIX__
Ben Noordhuisb4def482010-10-15 13:48:341899 String::Utf8Value key(property);
1900 const char* val = getenv(*key);
1901 if (val) {
Ben Noordhuisb4def482010-10-15 13:48:341902 return scope.Close(String::New(val));
1903 }
Bert Belder077f9d72012-02-15 22:34:181904#else // _WIN32
1905 String::Value key(property);
1906 WCHAR buffer[32767]; // The maximum size allowed for environment variables.
1907 DWORD result = GetEnvironmentVariableW(reinterpret_cast<WCHAR*>(*key),
1908 buffer,
1909 ARRAY_SIZE(buffer));
1910 // If result >= sizeof buffer the buffer was too small. That should never
1911 // happen. If result == 0 and result != ERROR_SUCCESS the variable was not
1912 // not found.
1913 if ((result > 0 || GetLastError() == ERROR_SUCCESS) &&
1914 result < ARRAY_SIZE(buffer)) {
1915 return scope.Close(String::New(reinterpret_cast<uint16_t*>(buffer), result));
1916 }
1917#endif
Ben Noordhuisfee02db2012-06-29 15:29:321918 // Not found. Fetch from prototype.
1919 return scope.Close(info.Data().As<Object>()->Get(property));
Ben Noordhuisb4def482010-10-15 13:48:341920}
1921
1922
1923static Handle<Value> EnvSetter(Local<String> property,
1924 Local<Value> value,
1925 const AccessorInfo& info) {
Ryan Dahle6b06bc2011-08-11 00:14:231926 HandleScope scope;
Bert Belder077f9d72012-02-15 22:34:181927#ifdef __POSIX__
Ben Noordhuisb4def482010-10-15 13:48:341928 String::Utf8Value key(property);
1929 String::Utf8Value val(value);
1930 setenv(*key, *val, 1);
Bert Belder077f9d72012-02-15 22:34:181931#else // _WIN32
1932 String::Value key(property);
1933 String::Value val(value);
1934 WCHAR* key_ptr = reinterpret_cast<WCHAR*>(*key);
1935 // Environment variables that start with '=' are read-only.
1936 if (key_ptr[0] != L'=') {
1937 SetEnvironmentVariableW(key_ptr, reinterpret_cast<WCHAR*>(*val));
Ryan Dahle6b06bc2011-08-11 00:14:231938 }
Bert Belder30bab522010-11-25 00:09:061939#endif
Bert Belder077f9d72012-02-15 22:34:181940 // Whether it worked or not, always return rval.
1941 return scope.Close(value);
Ben Noordhuisb4def482010-10-15 13:48:341942}
1943
1944
1945static Handle<Integer> EnvQuery(Local<String> property,
1946 const AccessorInfo& info) {
Bert Belder077f9d72012-02-15 22:34:181947 HandleScope scope;
1948#ifdef __POSIX__
Ben Noordhuisb4def482010-10-15 13:48:341949 String::Utf8Value key(property);
1950 if (getenv(*key)) {
Ben Noordhuisb4def482010-10-15 13:48:341951 return scope.Close(Integer::New(None));
1952 }
Bert Belder077f9d72012-02-15 22:34:181953#else // _WIN32
1954 String::Value key(property);
1955 WCHAR* key_ptr = reinterpret_cast<WCHAR*>(*key);
1956 if (GetEnvironmentVariableW(key_ptr, NULL, 0) > 0 ||
1957 GetLastError() == ERROR_SUCCESS) {
1958 if (key_ptr[0] == L'=') {
1959 // Environment variables that start with '=' are hidden and read-only.
1960 return scope.Close(Integer::New(v8::ReadOnly ||
1961 v8::DontDelete ||
1962 v8::DontEnum));
1963 } else {
1964 return scope.Close(Integer::New(None));
1965 }
1966 }
1967#endif
1968 // Not found
1969 return scope.Close(Handle<Integer>());
Ben Noordhuisb4def482010-10-15 13:48:341970}
1971
1972
1973static Handle<Boolean> EnvDeleter(Local<String> property,
1974 const AccessorInfo& info) {
Ryan Dahle6b06bc2011-08-11 00:14:231975 HandleScope scope;
Bert Belder30bab522010-11-25 00:09:061976#ifdef __POSIX__
Bert Belder077f9d72012-02-15 22:34:181977 String::Utf8Value key(property);
Ben Noordhuisdee8c512012-03-31 21:23:461978 if (!getenv(*key)) return False();
1979 unsetenv(*key); // can't check return value, it's void on some platforms
1980 return True();
Bert Belder30bab522010-11-25 00:09:061981#else
Bert Belder077f9d72012-02-15 22:34:181982 String::Value key(property);
1983 WCHAR* key_ptr = reinterpret_cast<WCHAR*>(*key);
1984 if (key_ptr[0] == L'=' || !SetEnvironmentVariableW(key_ptr, NULL)) {
1985 // Deletion failed. Return true if the key wasn't there in the first place,
1986 // false if it is still there.
1987 bool rv = GetEnvironmentVariableW(key_ptr, NULL, NULL) == 0 &&
1988 GetLastError() != ERROR_SUCCESS;
1989 return scope.Close(Boolean::New(rv));
Ben Noordhuisb4def482010-10-15 13:48:341990 }
Ben Noordhuisdee8c512012-03-31 21:23:461991 return True();
Bert Belder077f9d72012-02-15 22:34:181992#endif
Ben Noordhuisb4def482010-10-15 13:48:341993}
1994
1995
1996static Handle<Array> EnvEnumerator(const AccessorInfo& info) {
1997 HandleScope scope;
Bert Belder077f9d72012-02-15 22:34:181998#ifdef __POSIX__
Ben Noordhuisb4def482010-10-15 13:48:341999 int size = 0;
2000 while (environ[size]) size++;
2001
2002 Local<Array> env = Array::New(size);
2003
2004 for (int i = 0; i < size; ++i) {
2005 const char* var = environ[i];
2006 const char* s = strchr(var, '=');
2007 const int length = s ? s - var : strlen(var);
2008 env->Set(i, String::New(var, length));
2009 }
Bert Belder077f9d72012-02-15 22:34:182010#else // _WIN32
2011 WCHAR* environment = GetEnvironmentStringsW();
2012 if (environment == NULL) {
2013 // This should not happen.
2014 return scope.Close(Handle<Array>());
2015 }
2016 Local<Array> env = Array::New();
2017 WCHAR* p = environment;
2018 int i = 0;
2019 while (*p != NULL) {
2020 WCHAR *s;
2021 if (*p == L'=') {
2022 // If the key starts with '=' it is a hidden environment variable.
2023 p += wcslen(p) + 1;
2024 continue;
2025 } else {
2026 s = wcschr(p, L'=');
2027 }
2028 if (!s) {
2029 s = p + wcslen(p);
2030 }
2031 env->Set(i++, String::New(reinterpret_cast<uint16_t*>(p), s - p));
2032 p = s + wcslen(s) + 1;
2033 }
2034 FreeEnvironmentStringsW(environment);
2035#endif
Ben Noordhuisb4def482010-10-15 13:48:342036 return scope.Close(env);
2037}
2038
2039
Ben Noordhuisaa0308d2011-07-23 21:16:482040static Handle<Object> GetFeatures() {
2041 HandleScope scope;
2042
2043 Local<Object> obj = Object::New();
Ryan Dahl52a40e02011-08-24 21:16:352044 obj->Set(String::NewSymbol("debug"),
2045#if defined(DEBUG) && DEBUG
2046 True()
2047#else
2048 False()
2049#endif
2050 );
2051
Ryan Dahlc8dbaf52011-10-11 21:38:382052 obj->Set(String::NewSymbol("uv"), True());
Ben Noordhuisaa0308d2011-07-23 21:16:482053 obj->Set(String::NewSymbol("ipv6"), True()); // TODO ping libuv
Fedor Indutny9010f5f2011-07-28 15:52:042054 obj->Set(String::NewSymbol("tls_npn"), Boolean::New(use_npn));
2055 obj->Set(String::NewSymbol("tls_sni"), Boolean::New(use_sni));
Ben Noordhuisaa0308d2011-07-23 21:16:482056 obj->Set(String::NewSymbol("tls"),
2057 Boolean::New(get_builtin_module("crypto") != NULL));
2058
2059 return scope.Close(obj);
2060}
2061
2062
Fedor Indutny3f43b1c2012-02-12 15:53:432063static Handle<Value> DebugPortGetter(Local<String> property,
2064 const AccessorInfo& info) {
2065 HandleScope scope;
2066 return scope.Close(Integer::NewFromUnsigned(debug_port));
2067}
2068
2069
2070static void DebugPortSetter(Local<String> property,
2071 Local<Value> value,
2072 const AccessorInfo& info) {
2073 HandleScope scope;
2074 debug_port = value->NumberValue();
2075}
2076
2077
Bert Belder829735e2011-11-04 15:23:022078static Handle<Value> DebugProcess(const Arguments& args);
Fedor Indutnyb0388cc2011-12-10 16:52:072079static Handle<Value> DebugPause(const Arguments& args);
Fedor Indutny3f43b1c2012-02-12 15:53:432080static Handle<Value> DebugEnd(const Arguments& args);
Bert Belder829735e2011-11-04 15:23:022081
Dean McNameef67e8f22011-03-15 22:39:162082Handle<Object> SetupProcessObject(int argc, char *argv[]) {
Ryan27b268b2009-06-17 13:05:442083 HandleScope scope;
2084
Ryan Dahlcd1ec272011-01-02 09:44:422085 int i, j;
2086
Ryan Dahlad0a4ce2009-10-29 22:34:102087 Local<FunctionTemplate> process_template = FunctionTemplate::New();
Ryan27b268b2009-06-17 13:05:442088
Andreas Madsen6d70a4a2012-05-22 09:06:052089 process_template->SetClassName(String::NewSymbol("process"));
Ryan Dahlad0a4ce2009-10-29 22:34:102090
Andreas Madsen6d70a4a2012-05-22 09:06:052091 process = Persistent<Object>::New(process_template->GetFunction()->NewInstance());
Ben Noordhuis74a82152012-02-03 15:32:002092
Ryan Dahl5185c152010-06-18 07:26:492093 process->SetAccessor(String::New("title"),
2094 ProcessTitleGetter,
2095 ProcessTitleSetter);
2096
Ryan Dahlf4811832009-11-02 23:21:002097 // process.version
Ryan Dahlad0a4ce2009-10-29 22:34:102098 process->Set(String::NewSymbol("version"), String::New(NODE_VERSION));
Ryan Dahl39b432e2010-08-17 18:24:102099
Ryan Dahlea9ee1f2011-07-28 02:30:322100 // process.moduleLoadList
2101 module_load_list = Persistent<Array>::New(Array::New());
2102 process->Set(String::NewSymbol("moduleLoadList"), module_load_list);
2103
Nathan Rajlich35043ad2012-03-13 23:04:172104 // process.versions
Ryan Dahl39b432e2010-08-17 18:24:102105 Local<Object> versions = Object::New();
Ryan Dahl39b432e2010-08-17 18:24:102106 process->Set(String::NewSymbol("versions"), versions);
Nathan Rajlich36761b22012-03-08 20:25:402107 versions->Set(String::NewSymbol("http_parser"), String::New(
2108 NODE_STRINGIFY(HTTP_PARSER_VERSION_MAJOR) "."
2109 NODE_STRINGIFY(HTTP_PARSER_VERSION_MINOR)));
Ryan Dahl39b432e2010-08-17 18:24:102110 // +1 to get rid of the leading 'v'
2111 versions->Set(String::NewSymbol("node"), String::New(NODE_VERSION+1));
2112 versions->Set(String::NewSymbol("v8"), String::New(V8::GetVersion()));
2113 versions->Set(String::NewSymbol("ares"), String::New(ARES_VERSION_STR));
Nathan Rajlich35043ad2012-03-13 23:04:172114 versions->Set(String::NewSymbol("uv"), String::New(
2115 NODE_STRINGIFY(UV_VERSION_MAJOR) "."
2116 NODE_STRINGIFY(UV_VERSION_MINOR)));
Nathan Rajlich9701f1c2012-03-08 18:56:592117 versions->Set(String::NewSymbol("zlib"), String::New(ZLIB_VERSION));
Peter Bright13d6a1f2011-08-06 04:23:252118#if HAVE_OPENSSL
Ryan Dahlcd1ec272011-01-02 09:44:422119 // Stupid code to slice out the version string.
2120 int c, l = strlen(OPENSSL_VERSION_TEXT);
Ben Noordhuise0297ca2011-10-14 15:05:022121 for (i = j = 0; i < l; i++) {
Ryan Dahlcd1ec272011-01-02 09:44:422122 c = OPENSSL_VERSION_TEXT[i];
2123 if ('0' <= c && c <= '9') {
2124 for (j = i + 1; j < l; j++) {
2125 c = OPENSSL_VERSION_TEXT[j];
2126 if (c == ' ') break;
2127 }
2128 break;
2129 }
2130 }
2131 versions->Set(String::NewSymbol("openssl"),
2132 String::New(OPENSSL_VERSION_TEXT + i, j - i));
2133#endif
Ryan Dahl39b432e2010-08-17 18:24:102134
2135
2136
Nathan Rajlichb1be5402011-04-26 03:24:512137 // process.arch
2138 process->Set(String::NewSymbol("arch"), String::New(ARCH));
2139
Ryan Dahlf4811832009-11-02 23:21:002140 // process.platform
Ryan Dahl37704622011-01-06 03:05:592141 process->Set(String::NewSymbol("platform"), String::New(PLATFORM));
Ryan Dahlf4811832009-11-02 23:21:002142
Ryan Dahlf3ad6352010-02-03 20:19:082143 // process.argv
Jeremy Ashkenas2916a2a2010-02-21 06:41:272144 Local<Array> arguments = Array::New(argc - option_end_index + 1);
Ryan1910c112009-09-11 18:05:222145 arguments->Set(Integer::New(0), String::New(argv[0]));
Peter Griess78d33f42010-06-04 15:29:102146 for (j = 1, i = option_end_index; i < argc; j++, i++) {
Ryan27b268b2009-06-17 13:05:442147 Local<String> arg = String::New(argv[i]);
Ryan1910c112009-09-11 18:05:222148 arguments->Set(Integer::New(j), arg);
Ryan27b268b2009-06-17 13:05:442149 }
Ryan Dahl38814552009-10-09 15:15:472150 // assign it
Ryan Dahlf3ad6352010-02-03 20:19:082151 process->Set(String::NewSymbol("argv"), arguments);
Ryan27b268b2009-06-17 13:05:442152
Micheil Smith19fd5302012-03-05 17:53:152153 // process.execArgv
2154 Local<Array> execArgv = Array::New(option_end_index - 1);
2155 for (j = 1, i = 0; j < option_end_index; j++, i++) {
2156 execArgv->Set(Integer::New(i), String::New(argv[j]));
2157 }
2158 // assign it
2159 process->Set(String::NewSymbol("execArgv"), execArgv);
2160
2161
Ryan Dahlf3ad6352010-02-03 20:19:082162 // create process.env
Ben Noordhuisb4def482010-10-15 13:48:342163 Local<ObjectTemplate> envTemplate = ObjectTemplate::New();
Ryan Dahlea9006a2010-12-02 23:59:352164 envTemplate->SetNamedPropertyHandler(EnvGetter,
2165 EnvSetter,
2166 EnvQuery,
2167 EnvDeleter,
2168 EnvEnumerator,
Ben Noordhuisfee02db2012-06-29 15:29:322169 Object::New());
Ben Noordhuisb4def482010-10-15 13:48:342170 Local<Object> env = envTemplate->NewInstance();
Ryan Dahlf3ad6352010-02-03 20:19:082171 process->Set(String::NewSymbol("env"), env);
2172
Brandon Beacher334d56d2009-10-14 21:56:122173 process->Set(String::NewSymbol("pid"), Integer::New(getpid()));
Ben Noordhuisaa0308d2011-07-23 21:16:482174 process->Set(String::NewSymbol("features"), GetFeatures());
Ryandc39e822009-09-10 12:07:352175
TJ Holowaychuk9481bc12010-10-07 02:05:012176 // -e, --eval
2177 if (eval_string) {
2178 process->Set(String::NewSymbol("_eval"), String::New(eval_string));
Nathan Rajlichef3a8742012-04-24 08:24:132179 }
2180
2181 // -p, --print
2182 if (print_eval) {
2183 process->Set(String::NewSymbol("_print_eval"), True());
TJ Holowaychuk9481bc12010-10-07 02:05:012184 }
2185
Nathan Rajlich6292df62012-04-24 08:32:332186 // -i, --interactive
Nathan Rajlichfeaa8a42012-03-21 07:05:252187 if (force_repl) {
2188 process->Set(String::NewSymbol("_forceRepl"), True());
2189 }
2190
isaacs5b399292012-06-21 18:42:332191 // --no-deprecation
2192 if (no_deprecation) {
2193 process->Set(String::NewSymbol("noDeprecation"), True());
2194 }
2195
2196 // --trace-deprecation
2197 if (trace_deprecation) {
2198 process->Set(String::NewSymbol("traceDeprecation"), True());
2199 }
2200
Marshall Culpepperca35ba62010-06-22 06:31:192201 size_t size = 2*PATH_MAX;
Peter Bright13d6a1f2011-08-06 04:23:252202 char* execPath = new char[size];
Ryan Dahl48f65b32011-07-15 17:46:112203 if (uv_exepath(execPath, &size) != 0) {
Marshall Culpepperca35ba62010-06-22 06:31:192204 // as a last ditch effort, fallback on argv[0] ?
2205 process->Set(String::NewSymbol("execPath"), String::New(argv[0]));
2206 } else {
Ryan Dahl00a1d612010-11-16 03:06:182207 process->Set(String::NewSymbol("execPath"), String::New(execPath, size));
Marshall Culpepperca35ba62010-06-22 06:31:192208 }
Peter Bright13d6a1f2011-08-06 04:23:252209 delete [] execPath;
Marshall Culpepperca35ba62010-06-22 06:31:192210
Maciej Małecki977e2112012-02-17 18:35:052211 process->SetAccessor(String::New("debugPort"),
Fedor Indutny3f43b1c2012-02-12 15:53:432212 DebugPortGetter,
2213 DebugPortSetter);
2214
Marshall Culpepperca35ba62010-06-22 06:31:192215
Ryan Dahl38814552009-10-09 15:15:472216 // define various internal methods
Ben Noordhuis5f040652012-04-28 16:45:102217 NODE_SET_METHOD(process, "_getActiveRequests", GetActiveRequests);
2218 NODE_SET_METHOD(process, "_getActiveHandles", GetActiveHandles);
Ryan Dahl4e7e2f82010-04-13 22:39:152219 NODE_SET_METHOD(process, "_needTickCallback", NeedTickCallback);
Ryan Dahlad0a4ce2009-10-29 22:34:102220 NODE_SET_METHOD(process, "reallyExit", Exit);
Robert Mustacchi22404862011-12-15 01:02:152221 NODE_SET_METHOD(process, "abort", Abort);
Brandon Beacher47fcf782009-11-03 18:13:382222 NODE_SET_METHOD(process, "chdir", Chdir);
Ryan Dahlad0a4ce2009-10-29 22:34:102223 NODE_SET_METHOD(process, "cwd", Cwd);
Bert Belder30bab522010-11-25 00:09:062224
Ryan Dahlacc120a2011-08-09 20:53:562225 NODE_SET_METHOD(process, "umask", Umask);
2226
Bert Belder30bab522010-11-25 00:09:062227#ifdef __POSIX__
Michael Cartera3860762010-02-08 06:13:102228 NODE_SET_METHOD(process, "getuid", GetUid);
2229 NODE_SET_METHOD(process, "setuid", SetUid);
James Duncandf1c1e52010-02-23 22:45:022230
2231 NODE_SET_METHOD(process, "setgid", SetGid);
2232 NODE_SET_METHOD(process, "getgid", GetGid);
Igor Zinkovsky24a69d22011-11-02 22:06:482233#endif // __POSIX__
James Duncandf1c1e52010-02-23 22:45:022234
Ryan Dahl6eca9482010-09-17 06:13:032235 NODE_SET_METHOD(process, "_kill", Kill);
Bert Belder30bab522010-11-25 00:09:062236
Bert Belder829735e2011-11-04 15:23:022237 NODE_SET_METHOD(process, "_debugProcess", DebugProcess);
Fedor Indutnyb0388cc2011-12-10 16:52:072238 NODE_SET_METHOD(process, "_debugPause", DebugPause);
Fedor Indutny3f43b1c2012-02-12 15:53:432239 NODE_SET_METHOD(process, "_debugEnd", DebugEnd);
Bert Belder829735e2011-11-04 15:23:022240
Nathan Rajlich07c886f2012-03-05 16:51:582241 NODE_SET_METHOD(process, "hrtime", Hrtime);
2242
Bert Belderdd93c532011-10-28 10:05:092243 NODE_SET_METHOD(process, "dlopen", DLOpen);
2244
Tom Hughescf78ce52011-03-04 23:57:542245 NODE_SET_METHOD(process, "uptime", Uptime);
Ryan Dahlb3b3cfe2009-11-03 12:00:422246 NODE_SET_METHOD(process, "memoryUsage", MemoryUsage);
Ryan27b268b2009-06-17 13:05:442247
Ryan Dahl627fb5a2010-03-15 20:48:032248 NODE_SET_METHOD(process, "binding", Binding);
2249
Dean McNameef67e8f22011-03-15 22:39:162250 return process;
2251}
2252
2253
2254static void AtExit() {
Ryan Dahl4e43afd2011-09-30 20:11:472255 uv_tty_reset_mode();
Dean McNameef67e8f22011-03-15 22:39:162256}
2257
2258
2259static void SignalExit(int signal) {
Ryan Dahl4e43afd2011-09-30 20:11:472260 uv_tty_reset_mode();
Dean McNameef67e8f22011-03-15 22:39:162261 _exit(1);
2262}
2263
2264
Ryan Dahl7547c7d2011-12-07 01:00:332265void Load(Handle<Object> process_l) {
Ryan Dahl9f5643f2010-01-31 07:22:342266 // Compile, execute the src/node.js file. (Which was included as static C
2267 // string in node_natives.h. 'natve_node' is the string containing that
2268 // source code.)
Ryan Dahlb20c3432010-02-12 05:55:082269
Ryan Dahl9f5643f2010-01-31 07:22:342270 // The node.js file returns a function 'f'
Dean McNameef67e8f22011-03-15 22:39:162271 atexit(AtExit);
2272
Ryan Dahl9f5643f2010-01-31 07:22:342273 TryCatch try_catch;
Ryan Dahl9f5643f2010-01-31 07:22:342274
Tom Hughes74954ce2011-03-08 06:00:512275 Local<Value> f_value = ExecuteString(MainSource(),
2276 IMMUTABLE_STRING("node.js"));
Ryan Dahl9f5643f2010-01-31 07:22:342277 if (try_catch.HasCaught()) {
Ryan Dahlab068db2010-05-09 20:54:582278 ReportException(try_catch, true);
Ryan Dahl9f5643f2010-01-31 07:22:342279 exit(10);
2280 }
Ryan Dahl9f5643f2010-01-31 07:22:342281 assert(f_value->IsFunction());
2282 Local<Function> f = Local<Function>::Cast(f_value);
2283
2284 // Now we call 'f' with the 'process' variable that we've built up with
2285 // all our bindings. Inside node.js we'll take care of assigning things to
2286 // their places.
Ryan Dahlb20c3432010-02-12 05:55:082287
Ryan Dahl9f5643f2010-01-31 07:22:342288 // We start the process this way in order to be more modular. Developers
2289 // who do not like how 'src/node.js' setups the module system but do like
2290 // Node's I/O bindings may want to replace 'f' with their own function.
2291
Ryan Dahlf8ce8482010-09-17 07:01:072292 // Add a reference to the global object
2293 Local<Object> global = v8::Context::GetCurrent()->Global();
Ryan Dahl7547c7d2011-12-07 01:00:332294 Local<Value> args[1] = { Local<Value>::New(process_l) };
Zoran Tomicicd98ea702010-02-22 05:15:442295
Igor Zinkovsky35a14212012-06-11 23:23:172296#if defined HAVE_DTRACE || defined HAVE_ETW
Ryan Dahl068b7332011-01-25 01:50:102297 InitDTrace(global);
Ryan Dahle9257b82011-02-10 02:50:262298#endif
Ryan Dahl068b7332011-01-25 01:50:102299
Ryan Dahlb20c3432010-02-12 05:55:082300 f->Call(global, 1, args);
Ryan Dahl9f5643f2010-01-31 07:22:342301
Ryan Dahl8a52fb72010-07-01 18:10:222302 if (try_catch.HasCaught()) {
2303 ReportException(try_catch, true);
2304 exit(11);
Ryan Dahl9f5643f2010-01-31 07:22:342305 }
Ryan27b268b2009-06-17 13:05:442306}
2307
Zoran Tomicicd98ea702010-02-22 05:15:442308static void PrintHelp();
2309
2310static void ParseDebugOpt(const char* arg) {
2311 const char *p = 0;
2312
2313 use_debug_agent = true;
2314 if (!strcmp (arg, "--debug-brk")) {
2315 debug_wait_connect = true;
2316 return;
2317 } else if (!strcmp(arg, "--debug")) {
2318 return;
2319 } else if (strstr(arg, "--debug-brk=") == arg) {
2320 debug_wait_connect = true;
2321 p = 1 + strchr(arg, '=');
2322 debug_port = atoi(p);
2323 } else if (strstr(arg, "--debug=") == arg) {
2324 p = 1 + strchr(arg, '=');
2325 debug_port = atoi(p);
2326 }
2327 if (p && debug_port > 1024 && debug_port < 65536)
2328 return;
2329
2330 fprintf(stderr, "Bad debug option.\n");
2331 if (p) fprintf(stderr, "Debug port must be in range 1025 to 65535.\n");
2332
2333 PrintHelp();
2334 exit(1);
2335}
2336
Ryand6c9d312009-09-11 14:02:292337static void PrintHelp() {
Steve Engledow292345f2011-07-05 11:07:082338 printf("Usage: node [options] [ -e script | script.js ] [arguments] \n"
Ryan Dahl87339a22011-10-12 09:56:292339 " node debug script.js [arguments] \n"
Ryan Dahl4fa712c2011-01-13 23:28:162340 "\n"
Ryan Dahl209b2192010-03-08 16:33:102341 "Options:\n"
Tom Hughes78da9cb2010-10-18 22:50:562342 " -v, --version print node's version\n"
Steve Engledow292345f2011-07-05 11:07:082343 " -e, --eval script evaluate script\n"
Ben Noordhuis3d22dbf2011-12-01 16:21:002344 " -p, --print print result of --eval\n"
Nathan Rajlichfeaa8a42012-03-21 07:05:252345 " -i, --interactive always enter the REPL even if stdin\n"
2346 " does not appear to be a terminal\n"
isaacs5b399292012-06-21 18:42:332347 " --no-deprecation silence deprecation warnings\n"
2348 " --trace-deprecation show stack traces on deprecations\n"
Tom Hughes78da9cb2010-10-18 22:50:562349 " --v8-options print v8 command line options\n"
Tom Hughes78da9cb2010-10-18 22:50:562350 " --max-stack-size=val set max v8 stack size (bytes)\n"
Ryan Dahl209b2192010-03-08 16:33:102351 "\n"
Ben Noordhuisfdf180f2011-12-05 07:42:112352 "Environment variables:\n"
2353#ifdef _WIN32
2354 "NODE_PATH ';'-separated list of directories\n"
2355#else
Tom Hughes78da9cb2010-10-18 22:50:562356 "NODE_PATH ':'-separated list of directories\n"
Ben Noordhuisfdf180f2011-12-05 07:42:112357#endif
isaacsc050d0f2011-07-25 01:04:452358 " prefixed to the module search path.\n"
Tom Hughes78da9cb2010-10-18 22:50:562359 "NODE_MODULE_CONTEXTS Set to 1 to load modules in their own\n"
2360 " global contexts.\n"
Ryan Dahl4fa712c2011-01-13 23:28:162361 "NODE_DISABLE_COLORS Set to 1 to disable colors in the REPL\n"
Ryan Dahl209b2192010-03-08 16:33:102362 "\n"
Ryan Dahl4fa712c2011-01-13 23:28:162363 "Documentation can be found at http://nodejs.org/\n");
Ryan11df2522009-08-03 16:19:402364}
2365
Ryan Dahl38814552009-10-09 15:15:472366// Parse node command line arguments.
Dean McNameef67e8f22011-03-15 22:39:162367static void ParseArgs(int argc, char **argv) {
Peter Griess78d33f42010-06-04 15:29:102368 int i;
2369
Ryan Dahle742d072009-10-09 11:25:042370 // TODO use parse opts
Dean McNameef67e8f22011-03-15 22:39:162371 for (i = 1; i < argc; i++) {
Ryan11df2522009-08-03 16:19:402372 const char *arg = argv[i];
Zoran Tomicicd98ea702010-02-22 05:15:442373 if (strstr(arg, "--debug") == arg) {
2374 ParseDebugOpt(arg);
Jonas Pfenniger8f59ccc2010-02-24 21:11:082375 argv[i] = const_cast<char*>("");
Ryan1910c112009-09-11 18:05:222376 } else if (strcmp(arg, "--version") == 0 || strcmp(arg, "-v") == 0) {
Ryan11df2522009-08-03 16:19:402377 printf("%s\n", NODE_VERSION);
2378 exit(0);
Tom Hughes78da9cb2010-10-18 22:50:562379 } else if (strstr(arg, "--max-stack-size=") == arg) {
2380 const char *p = 0;
2381 p = 1 + strchr(arg, '=');
2382 max_stack_size = atoi(p);
2383 argv[i] = const_cast<char*>("");
Ryan11df2522009-08-03 16:19:402384 } else if (strcmp(arg, "--help") == 0 || strcmp(arg, "-h") == 0) {
2385 PrintHelp();
2386 exit(0);
Ben Noordhuisf03c3202012-09-03 14:42:182387 } else if (strcmp(arg, "--eval") == 0 ||
2388 strcmp(arg, "-e") == 0 ||
2389 strcmp(arg, "--print") == 0 ||
2390 strcmp(arg, "-pe") == 0 ||
2391 strcmp(arg, "-p") == 0) {
Dean McNameef67e8f22011-03-15 22:39:162392 if (argc <= i + 1) {
Ben Noordhuisf03c3202012-09-03 14:42:182393 fprintf(stderr, "Error: %s requires an argument\n", arg);
TJ Holowaychuk9481bc12010-10-07 02:05:012394 exit(1);
2395 }
Ben Noordhuisf03c3202012-09-03 14:42:182396 print_eval = print_eval || strchr(arg, 'p') != NULL;
TJ Holowaychuk9481bc12010-10-07 02:05:012397 argv[i] = const_cast<char*>("");
2398 eval_string = argv[++i];
Nathan Rajlichfeaa8a42012-03-21 07:05:252399 } else if (strcmp(arg, "--interactive") == 0 || strcmp(arg, "-i") == 0) {
2400 force_repl = true;
2401 argv[i] = const_cast<char*>("");
Ryan11df2522009-08-03 16:19:402402 } else if (strcmp(arg, "--v8-options") == 0) {
Jonas Pfenniger8f59ccc2010-02-24 21:11:082403 argv[i] = const_cast<char*>("--help");
isaacs5b399292012-06-21 18:42:332404 } else if (strcmp(arg, "--no-deprecation") == 0) {
2405 argv[i] = const_cast<char*>("");
2406 no_deprecation = true;
2407 } else if (strcmp(arg, "--trace-deprecation") == 0) {
2408 argv[i] = const_cast<char*>("");
2409 trace_deprecation = true;
Jeremy Ashkenas2916a2a2010-02-21 06:41:272410 } else if (argv[i][0] != '-') {
Jeremy Ashkenas2916a2a2010-02-21 06:41:272411 break;
Ryan11df2522009-08-03 16:19:402412 }
2413 }
Peter Griess78d33f42010-06-04 15:29:102414
2415 option_end_index = i;
Ryan11df2522009-08-03 16:19:402416}
2417
Bert Belder829735e2011-11-04 15:23:022418
Ben Noordhuis74a82152012-02-03 15:32:002419static Isolate* node_isolate = NULL;
2420static volatile bool debugger_running = false;
2421
Peter Rybin688859a2012-07-03 19:21:372422
2423static uv_async_t dispatch_debug_messages_async;
2424
2425
2426// Called from the main thread.
2427static void DispatchDebugMessagesAsyncCallback(uv_async_t* handle, int status) {
2428 v8::Debug::ProcessDebugMessages();
2429}
2430
2431
2432// Called from V8 Debug Agent TCP thread.
2433static void DispatchMessagesDebugAgentCallback() {
2434 uv_async_send(&dispatch_debug_messages_async);
2435}
2436
2437
Ryan Dahl2a7e7b12010-12-18 19:17:292438static void EnableDebug(bool wait_connect) {
Bert Belder829735e2011-11-04 15:23:022439 // If we're called from another thread, make sure to enter the right
2440 // v8 isolate.
2441 node_isolate->Enter();
2442
Peter Rybin688859a2012-07-03 19:21:372443 v8::Debug::SetDebugMessageDispatchHandler(DispatchMessagesDebugAgentCallback,
2444 false);
2445
2446 uv_async_init(uv_default_loop(),
2447 &dispatch_debug_messages_async,
2448 DispatchDebugMessagesAsyncCallback);
2449 uv_unref((uv_handle_t*) &dispatch_debug_messages_async);
2450
Ryan Dahl2a7e7b12010-12-18 19:17:292451 // Start the debug thread and it's associated TCP server on port 5858.
Fedor Indutny5e8c2b02012-03-27 18:37:542452 bool r = v8::Debug::EnableAgent("node " NODE_VERSION,
2453 debug_port,
2454 wait_connect);
Ryan Dahl2a7e7b12010-12-18 19:17:292455
2456 // Crappy check that everything went well. FIXME
2457 assert(r);
2458
2459 // Print out some information.
Fedor Indutny26aab0d2011-09-24 07:28:272460 fprintf(stderr, "debugger listening on port %d\n", debug_port);
Bert Belder829735e2011-11-04 15:23:022461 fflush(stderr);
Fedor Indutny9e09fc02011-09-24 05:44:082462
2463 debugger_running = true;
Bert Belder829735e2011-11-04 15:23:022464
2465 node_isolate->Exit();
Ryan Dahl2a7e7b12010-12-18 19:17:292466}
2467
2468
Fedor Indutny82d0ac72011-09-24 13:51:592469#ifdef __POSIX__
Fedor Indutny26aab0d2011-09-24 07:28:272470static void EnableDebugSignalHandler(int signal) {
2471 // Break once process will return execution to v8
Bert Belder829735e2011-11-04 15:23:022472 v8::Debug::DebugBreak(node_isolate);
Ryan Dahl4ab54762011-03-01 17:59:172473
Fedor Indutny26aab0d2011-09-24 07:28:272474 if (!debugger_running) {
Ryan Dahl4ab54762011-03-01 17:59:172475 fprintf(stderr, "Hit SIGUSR1 - starting debugger agent.\n");
2476 EnableDebug(false);
2477 }
Ryan Dahl2a7e7b12010-12-18 19:17:292478}
2479
2480
Bert Belder829735e2011-11-04 15:23:022481static void RegisterSignalHandler(int signal, void (*handler)(int)) {
Tom Hughesf61b1102010-10-12 21:01:582482 struct sigaction sa;
2483
2484 memset(&sa, 0, sizeof(sa));
2485 sa.sa_handler = handler;
2486 sigfillset(&sa.sa_mask);
Bert Belder829735e2011-11-04 15:23:022487 sigaction(signal, &sa, NULL);
2488}
2489
2490
2491Handle<Value> DebugProcess(const Arguments& args) {
2492 HandleScope scope;
2493
2494 if (args.Length() != 1) {
2495 return ThrowException(Exception::Error(
2496 String::New("Invalid number of arguments.")));
2497 }
2498
2499 pid_t pid;
2500 int r;
2501
2502 pid = args[0]->IntegerValue();
2503 r = kill(pid, SIGUSR1);
2504 if (r != 0) {
2505 return ThrowException(ErrnoException(errno, "kill"));
2506 }
2507
2508 return Undefined();
Tom Hughesf61b1102010-10-12 21:01:582509}
Bert Belder30bab522010-11-25 00:09:062510#endif // __POSIX__
Tom Hughesf61b1102010-10-12 21:01:582511
2512
Bert Belder829735e2011-11-04 15:23:022513#ifdef _WIN32
2514DWORD WINAPI EnableDebugThreadProc(void* arg) {
2515 // Break once process will return execution to v8
2516 if (!debugger_running) {
2517 for (int i = 0; i < 1; i++) {
2518 fprintf(stderr, "Starting debugger agent.\r\n");
2519 fflush(stderr);
2520 EnableDebug(false);
2521 }
2522 }
2523
2524 v8::Debug::DebugBreak();
2525
2526 return 0;
2527}
2528
2529
Bert Belder8f2694b2012-02-16 21:19:482530static int GetDebugSignalHandlerMappingName(DWORD pid, wchar_t* buf,
2531 size_t buf_len) {
2532 return _snwprintf(buf, buf_len, L"node-debug-handler-%u", pid);
Bert Belder829735e2011-11-04 15:23:022533}
2534
2535
2536static int RegisterDebugSignalHandler() {
Bert Belder8f2694b2012-02-16 21:19:482537 wchar_t mapping_name[32];
Bert Belder829735e2011-11-04 15:23:022538 HANDLE mapping_handle;
2539 DWORD pid;
2540 LPTHREAD_START_ROUTINE* handler;
2541
2542 pid = GetCurrentProcessId();
2543
2544 if (GetDebugSignalHandlerMappingName(pid,
2545 mapping_name,
Bert Belder8f2694b2012-02-16 21:19:482546 ARRAY_SIZE(mapping_name)) < 0) {
Bert Belder829735e2011-11-04 15:23:022547 return -1;
2548 }
2549
Bert Belder8f2694b2012-02-16 21:19:482550 mapping_handle = CreateFileMappingW(INVALID_HANDLE_VALUE,
Bert Belder829735e2011-11-04 15:23:022551 NULL,
2552 PAGE_READWRITE,
2553 0,
2554 sizeof *handler,
2555 mapping_name);
2556 if (mapping_handle == NULL) {
2557 return -1;
2558 }
2559
Bert Belder8f2694b2012-02-16 21:19:482560 handler = reinterpret_cast<LPTHREAD_START_ROUTINE*>(
2561 MapViewOfFile(mapping_handle,
2562 FILE_MAP_ALL_ACCESS,
2563 0,
2564 0,
2565 sizeof *handler));
Bert Belder829735e2011-11-04 15:23:022566 if (handler == NULL) {
2567 CloseHandle(mapping_handle);
2568 return -1;
2569 }
2570
2571 *handler = EnableDebugThreadProc;
2572
2573 UnmapViewOfFile((void*) handler);
2574
2575 return 0;
2576}
2577
2578
2579static Handle<Value> DebugProcess(const Arguments& args) {
2580 HandleScope scope;
2581 Handle<Value> rv = Undefined();
2582 DWORD pid;
Bert Belder68db2062012-02-03 14:37:462583 HANDLE process = NULL;
Bert Belder829735e2011-11-04 15:23:022584 HANDLE thread = NULL;
2585 HANDLE mapping = NULL;
Bert Belder8f2694b2012-02-16 21:19:482586 wchar_t mapping_name[32];
Bert Belder829735e2011-11-04 15:23:022587 LPTHREAD_START_ROUTINE* handler = NULL;
2588
2589 if (args.Length() != 1) {
2590 rv = ThrowException(Exception::Error(String::New("Invalid number of arguments.")));
2591 goto out;
2592 }
2593
2594 pid = (DWORD) args[0]->IntegerValue();
2595
Bert Belder68db2062012-02-03 14:37:462596 process = OpenProcess(PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION |
Bert Belder829735e2011-11-04 15:23:022597 PROCESS_VM_OPERATION | PROCESS_VM_WRITE |
2598 PROCESS_VM_READ,
2599 FALSE,
2600 pid);
Bert Belder68db2062012-02-03 14:37:462601 if (process == NULL) {
Bert Belder829735e2011-11-04 15:23:022602 rv = ThrowException(WinapiErrnoException(GetLastError(), "OpenProcess"));
2603 goto out;
2604 }
2605
2606 if (GetDebugSignalHandlerMappingName(pid,
2607 mapping_name,
Bert Belder8f2694b2012-02-16 21:19:482608 ARRAY_SIZE(mapping_name)) < 0) {
Bert Belder829735e2011-11-04 15:23:022609 rv = ThrowException(ErrnoException(errno, "sprintf"));
2610 goto out;
2611 }
2612
Bert Belder8f2694b2012-02-16 21:19:482613 mapping = OpenFileMappingW(FILE_MAP_READ, FALSE, mapping_name);
Bert Belder829735e2011-11-04 15:23:022614 if (mapping == NULL) {
Bert Belder8f2694b2012-02-16 21:19:482615 rv = ThrowException(WinapiErrnoException(GetLastError(),
2616 "OpenFileMappingW"));
Bert Belder829735e2011-11-04 15:23:022617 goto out;
2618 }
2619
Bert Belder8f2694b2012-02-16 21:19:482620 handler = reinterpret_cast<LPTHREAD_START_ROUTINE*>(
2621 MapViewOfFile(mapping,
2622 FILE_MAP_READ,
2623 0,
2624 0,
2625 sizeof *handler));
Bert Belder829735e2011-11-04 15:23:022626 if (handler == NULL || *handler == NULL) {
2627 rv = ThrowException(WinapiErrnoException(GetLastError(), "MapViewOfFile"));
2628 goto out;
2629 }
2630
Bert Belder68db2062012-02-03 14:37:462631 thread = CreateRemoteThread(process,
Bert Belder829735e2011-11-04 15:23:022632 NULL,
2633 0,
2634 *handler,
2635 NULL,
2636 0,
2637 NULL);
2638 if (thread == NULL) {
2639 rv = ThrowException(WinapiErrnoException(GetLastError(),
2640 "CreateRemoteThread"));
2641 goto out;
2642 }
2643
2644 // Wait for the thread to terminate
2645 if (WaitForSingleObject(thread, INFINITE) != WAIT_OBJECT_0) {
2646 rv = ThrowException(WinapiErrnoException(GetLastError(),
2647 "WaitForSingleObject"));
2648 goto out;
2649 }
2650
2651 out:
Bert Belder68db2062012-02-03 14:37:462652 if (process != NULL) {
2653 CloseHandle(process);
Bert Belder829735e2011-11-04 15:23:022654 }
2655 if (thread != NULL) {
2656 CloseHandle(thread);
2657 }
2658 if (handler != NULL) {
2659 UnmapViewOfFile(handler);
2660 }
2661 if (mapping != NULL) {
2662 CloseHandle(mapping);
2663 }
2664
2665 return Undefined();
2666}
2667#endif // _WIN32
2668
2669
Fedor Indutnyb0388cc2011-12-10 16:52:072670static Handle<Value> DebugPause(const Arguments& args) {
2671 v8::Debug::DebugBreak(node_isolate);
Ben Noordhuisaac717d2011-12-19 23:30:412672 return Undefined();
Fedor Indutnyb0388cc2011-12-10 16:52:072673}
2674
2675
Fedor Indutny3f43b1c2012-02-12 15:53:432676static Handle<Value> DebugEnd(const Arguments& args) {
2677 if (debugger_running) {
2678 v8::Debug::DisableAgent();
2679 debugger_running = false;
2680 }
2681
2682 return Undefined();
2683}
2684
2685
Ben Noordhuis74a82152012-02-03 15:32:002686char** Init(int argc, char *argv[]) {
2687 // Initialize prog_start_time to get relative uptime.
2688 uv_uptime(&prog_start_time);
2689
Bert Belder09be3602012-06-13 23:28:512690 // Make inherited handles noninheritable.
2691 uv_disable_stdio_inheritance();
2692
Ryan Dahl38814552009-10-09 15:15:472693 // Parse a few arguments which are specific to Node.
Dean McNameef67e8f22011-03-15 22:39:162694 node::ParseArgs(argc, argv);
Jeremy Ashkenas2916a2a2010-02-21 06:41:272695 // Parse the rest of the args (up to the 'option_end_index' (where '--' was
Ryan Dahl38814552009-10-09 15:15:472696 // in the command line))
Ryan Dahl7547c7d2011-12-07 01:00:332697 int v8argc = option_end_index;
Danny Coatesdc8c0792010-08-01 22:46:482698 char **v8argv = argv;
2699
Ryan Dahl7547c7d2011-12-07 01:00:332700 if (debug_wait_connect) {
Ryan Dahladec5442010-08-04 17:38:192701 // v8argv is a copy of argv up to the script file argument +2 if --debug-brk
Ryan Dahld408de82010-08-06 19:31:412702 // to expose the v8 debugger js object so that node.js can set
Ryan Dahladec5442010-08-04 17:38:192703 // a breakpoint on the first line of the startup script
2704 v8argc += 2;
2705 v8argv = new char*[v8argc];
Ryan Dahl7547c7d2011-12-07 01:00:332706 memcpy(v8argv, argv, sizeof(argv) * option_end_index);
2707 v8argv[option_end_index] = const_cast<char*>("--expose_debug_as");
2708 v8argv[option_end_index + 1] = const_cast<char*>("v8debug");
Ryan Dahladec5442010-08-04 17:38:192709 }
Tom Hughes78da9cb2010-10-18 22:50:562710
2711 // For the normal stack which moves from high to low addresses when frames
2712 // are pushed, we can compute the limit as stack_size bytes below the
2713 // the address of a stack variable (e.g. &stack_var) as an approximation
2714 // of the start of the stack (we're assuming that we haven't pushed a lot
2715 // of frames yet).
Ryan Dahl7547c7d2011-12-07 01:00:332716 if (max_stack_size != 0) {
Tom Hughes78da9cb2010-10-18 22:50:562717 uint32_t stack_var;
2718 ResourceConstraints constraints;
2719
Ryan Dahl7547c7d2011-12-07 01:00:332720 uint32_t *stack_limit = &stack_var - (max_stack_size / sizeof(uint32_t));
Tom Hughes78da9cb2010-10-18 22:50:562721 constraints.set_stack_limit(stack_limit);
2722 SetResourceConstraints(&constraints); // Must be done before V8::Initialize
2723 }
Danny Coatesdc8c0792010-08-01 22:46:482724 V8::SetFlagsFromCommandLine(&v8argc, v8argv, false);
Ryan23376302009-09-10 10:34:292725
Bert Belder30bab522010-11-25 00:09:062726#ifdef __POSIX__
Ryan Dahlb6c5cf62010-05-04 17:41:562727 // Ignore SIGPIPE
Tom Hughesf61b1102010-10-12 21:01:582728 RegisterSignalHandler(SIGPIPE, SIG_IGN);
2729 RegisterSignalHandler(SIGINT, SignalExit);
2730 RegisterSignalHandler(SIGTERM, SignalExit);
Bert Belder30bab522010-11-25 00:09:062731#endif // __POSIX__
Ryan Dahlb6c5cf62010-05-04 17:41:562732
Ben Noordhuis74a82152012-02-03 15:32:002733 uv_idle_init(uv_default_loop(), &tick_spinner);
Ben Noordhuis74a82152012-02-03 15:32:002734
2735 uv_check_init(uv_default_loop(), &gc_check);
2736 uv_check_start(&gc_check, node::Check);
Ben Noordhuis039fac62012-05-17 05:13:292737 uv_unref(reinterpret_cast<uv_handle_t*>(&gc_check));
Ben Noordhuis74a82152012-02-03 15:32:002738
2739 uv_idle_init(uv_default_loop(), &gc_idle);
Ben Noordhuis039fac62012-05-17 05:13:292740 uv_unref(reinterpret_cast<uv_handle_t*>(&gc_idle));
Ben Noordhuis74a82152012-02-03 15:32:002741
2742 uv_timer_init(uv_default_loop(), &gc_timer);
Ben Noordhuis039fac62012-05-17 05:13:292743 uv_unref(reinterpret_cast<uv_handle_t*>(&gc_timer));
Ben Noordhuis74a82152012-02-03 15:32:002744
2745 V8::SetFatalErrorHandler(node::OnFatalError);
2746
2747 // Fetch a reference to the main isolate, so we have a reference to it
2748 // even when we need it to access it from another (debugger) thread.
2749 node_isolate = Isolate::GetCurrent();
2750
2751 // If the --debug flag was specified then initialize the debug thread.
2752 if (use_debug_agent) {
2753 EnableDebug(debug_wait_connect);
2754 } else {
2755#ifdef _WIN32
2756 RegisterDebugSignalHandler();
2757#else // Posix
2758 RegisterSignalHandler(SIGUSR1, EnableDebugSignalHandler);
2759#endif // __POSIX__
2760 }
2761
Ben Noordhuis5866f1a2011-12-09 18:02:332762 return argv;
2763}
Ben Noordhuis356992f2011-11-22 16:10:092764
Ben Noordhuis5866f1a2011-12-09 18:02:332765
Ben Noordhuise4a8d262012-04-21 05:13:252766struct AtExitCallback {
2767 AtExitCallback* next_;
2768 void (*cb_)(void* arg);
2769 void* arg_;
2770};
2771
2772static AtExitCallback* at_exit_functions_;
2773
2774
2775void RunAtExit() {
2776 AtExitCallback* p = at_exit_functions_;
2777 at_exit_functions_ = NULL;
2778
2779 while (p) {
2780 AtExitCallback* q = p->next_;
2781 p->cb_(p->arg_);
2782 delete p;
2783 p = q;
2784 }
2785}
2786
2787
2788void AtExit(void (*cb)(void* arg), void* arg) {
2789 AtExitCallback* p = new AtExitCallback;
2790 p->cb_ = cb;
2791 p->arg_ = arg;
2792 p->next_ = at_exit_functions_;
2793 at_exit_functions_ = p;
2794}
2795
2796
Ben Noordhuis5866f1a2011-12-09 18:02:332797void EmitExit(v8::Handle<v8::Object> process_l) {
2798 // process.emit('exit')
Nathan Rajlichb8945212012-05-01 20:53:302799 process_l->Set(String::NewSymbol("_exiting"), True());
Ben Noordhuis5866f1a2011-12-09 18:02:332800 Local<Value> emit_v = process_l->Get(String::New("emit"));
2801 assert(emit_v->IsFunction());
2802 Local<Function> emit = Local<Function>::Cast(emit_v);
Nathan Rajlich248f5522012-04-30 01:53:412803 Local<Value> args[] = { String::New("exit"), Integer::New(0) };
Ben Noordhuis5866f1a2011-12-09 18:02:332804 TryCatch try_catch;
Nathan Rajlich248f5522012-04-30 01:53:412805 emit->Call(process_l, 2, args);
Ben Noordhuis5866f1a2011-12-09 18:02:332806 if (try_catch.HasCaught()) {
2807 FatalException(try_catch);
2808 }
2809}
2810
Micheil Smith19fd5302012-03-05 17:53:152811static char **copy_argv(int argc, char **argv) {
2812 size_t strlen_sum;
2813 char **argv_copy;
2814 char *argv_data;
2815 size_t len;
2816 int i;
2817
2818 strlen_sum = 0;
2819 for(i = 0; i < argc; i++) {
2820 strlen_sum += strlen(argv[i]) + 1;
2821 }
2822
2823 argv_copy = (char **) malloc(sizeof(char *) * (argc + 1) + strlen_sum);
2824 if (!argv_copy) {
2825 return NULL;
2826 }
2827
2828 argv_data = (char *) argv_copy + sizeof(char *) * (argc + 1);
2829
2830 for(i = 0; i < argc; i++) {
2831 argv_copy[i] = argv_data;
2832 len = strlen(argv[i]) + 1;
2833 memcpy(argv_data, argv[i], len);
2834 argv_data += len;
2835 }
2836
2837 argv_copy[argc] = NULL;
2838
2839 return argv_copy;
2840}
Ben Noordhuis5866f1a2011-12-09 18:02:332841
Ben Noordhuis74a82152012-02-03 15:32:002842int Start(int argc, char *argv[]) {
Ben Noordhuis1a979982012-03-15 22:10:322843 // Hack aroung with the argv pointer. Used for process.title = "blah".
2844 argv = uv_setup_args(argc, argv);
2845
Micheil Smith19fd5302012-03-05 17:53:152846 // Logic to duplicate argv as Init() modifies arguments
2847 // that are passed into it.
2848 char **argv_copy = copy_argv(argc, argv);
2849
Ben Noordhuis74a82152012-02-03 15:32:002850 // This needs to run *before* V8::Initialize()
Micheil Smith19fd5302012-03-05 17:53:152851 // Use copy here as to not modify the original argv:
2852 Init(argc, argv_copy);
Ben Noordhuis5866f1a2011-12-09 18:02:332853
Marcel Laverdetc33d3172012-05-04 22:29:422854 V8::Initialize();
2855 {
2856 Locker locker;
2857 HandleScope handle_scope;
Ben Noordhuis809fdf22011-12-09 20:49:102858
Marcel Laverdetc33d3172012-05-04 22:29:422859 // Create the one and only Context.
2860 Persistent<Context> context = Context::New();
2861 Context::Scope context_scope(context);
Ryan Dahle742d072009-10-09 11:25:042862
Ben Noordhuis636add22012-04-27 16:58:302863 process_symbol = NODE_PSYMBOL("process");
2864 domain_symbol = NODE_PSYMBOL("domain");
2865
Marcel Laverdetc33d3172012-05-04 22:29:422866 // Use original argv, as we're just copying values out of it.
2867 Handle<Object> process_l = SetupProcessObject(argc, argv);
2868 v8_typed_array::AttachBindings(context->Global());
Ryan Dahl4d02e772011-12-17 07:23:342869
Marcel Laverdetc33d3172012-05-04 22:29:422870 // Create all the objects, load modules, do everything.
2871 // so your next reading stop should be node::Load()!
2872 Load(process_l);
Ryan19478ed2009-03-03 00:56:152873
Marcel Laverdetc33d3172012-05-04 22:29:422874 // All our arguments are loaded. We've evaluated all of the scripts. We
2875 // might even have created TCP servers. Now we enter the main eventloop. If
2876 // there are no watchers on the loop (except for the ones that were
2877 // uv_unref'd) then this function exits. As long as there are active
2878 // watchers, it blocks.
2879 uv_run(uv_default_loop());
Ryan Dahlc7b24ef2010-11-12 00:33:212880
Marcel Laverdetc33d3172012-05-04 22:29:422881 EmitExit(process_l);
2882 RunAtExit();
Ben Noordhuis66116922011-11-23 19:50:282883
Ryan Dahl38814552009-10-09 15:15:472884#ifndef NDEBUG
Marcel Laverdetc33d3172012-05-04 22:29:422885 context.Dispose();
2886#endif
2887 }
2888
2889#ifndef NDEBUG
2890 // Clean up. Not strictly necessary.
Ryan27b268b2009-06-17 13:05:442891 V8::Dispose();
Ryan Dahl38814552009-10-09 15:15:472892#endif // NDEBUG
Igor Zinkovskya58b6432011-07-07 20:54:302893
Micheil Smith19fd5302012-03-05 17:53:152894 // Clean up the copy:
2895 free(argv_copy);
2896
Ryanf6a7fe22009-06-08 14:17:332897 return 0;
Ryan19478ed2009-03-03 00:56:152898}
Ryan Dahl124fbed2010-09-19 20:13:572899
2900
2901} // namespace node