Merge remote-tracking branch 'upstream/v0.10'
authorTimothy J Fontaine <tjfontaine@gmail.com>
Tue, 31 Dec 2013 22:57:46 +0000 (14:57 -0800)
committerTimothy J Fontaine <tjfontaine@gmail.com>
Tue, 31 Dec 2013 22:57:46 +0000 (14:57 -0800)
1  2 
doc/api/child_process.markdown
doc/api/process.markdown

@@@ -194,6 -194,11 +194,11 @@@ And then the child script, `'sub.js'` m
  In the child the `process` object will have a `send()` method, and `process`
  will emit objects each time it receives a message on its channel.
  
+ Please note that the `send()` method on both the parent and child are
+ synchronous - sending large chunks of data is not advised (pipes can be used
+ instead, see
+ [`child_process.spawn`](#child_process_child_process_spawn_command_args_options)).
  There is a special case when sending a `{cmd: 'NODE_foo'}` message. All messages
  containing a `NODE_` prefix in its `cmd` property will not be emitted in
  the `message` event, since they are internal messages used by node core.
@@@ -479,10 -484,6 +484,10 @@@ See also: `child_process.exec()` and `c
    * `cwd` {String} Current working directory of the child process
    * `env` {Object} Environment key-value pairs
    * `encoding` {String} (Default: 'utf8')
 +  * `shell` {String} Shell to execute the command with
 +    (Default: '/bin/sh' on UNIX, 'cmd.exe' on Windows,  The shell should
 +     understand the `-c` switch on UNIX or `/s /c` on Windows. On Windows,
 +     command line parsing should be compatible with `cmd.exe`.)
    * `timeout` {Number} (Default: 0)
    * `maxBuffer` {Number} (Default: `200*1024`)
    * `killSignal` {String} (Default: 'SIGTERM')
diff --combined doc/api/process.markdown
@@@ -5,65 -5,24 +5,68 @@@
  The `process` object is a global object and can be accessed from anywhere.
  It is an instance of [EventEmitter][].
  
 +## Exit Codes
 +
 +Node will normally exit with a `0` status code when no more async
 +operations are pending.  The following status codes are used in other
 +cases:
 +
 +* `1` **Uncaught Fatal Exception** - There was an uncaught exception,
 +  and it was not handled by a domain or an `uncaughtException` event
 +  handler.
 +* `2` - Unused (reserved by Bash for builtin misuse)
 +* `3` **Internal JavaScript Parse Error** - The JavaScript source code
 +  internal in Node's bootstrapping process caused a parse error.  This
 +  is extremely rare, and generally can only happen during development
 +  of Node itself.
 +* `4` **Internal JavaScript Evaluation Failure** - The JavaScript
 +  source code internal in Node's bootstrapping process failed to
 +  return a function value when evaluated.  This is extremely rare, and
 +  generally can only happen during development of Node itself.
 +* `5` **Fatal Error** - There was a fatal unrecoverable error in V8.
 +  Typically a message will be printed to stderr with the prefix `FATAL
 +  ERROR`.
 +* `6` **Non-function Internal Exception Handler** - There was an
 +  uncaught exception, but the internal fatal exception handler
 +  function was somehow set to a non-function, and could not be called.
 +* `7` **Internal Exception Handler Run-Time Failure** - There was an
 +  uncaught exception, and the internal fatal exception handler
 +  function itself threw an error while attempting to handle it.  This
 +  can happen, for example, if a `process.on('uncaughtException')` or
 +  `domain.on('error')` handler throws an error.
 +* `8` - Unused.  In previous versions of Node, exit code 8 sometimes
 +  indicated an uncaught exception.
 +* `9` - **Invalid Argument** - Either an unknown option was specified,
 +  or an option requiring a value was provided without a value.
 +* `10` **Internal JavaScript Run-Time Failure** - The JavaScript
 +  source code internal in Node's bootstrapping process threw an error
 +  when the bootstrapping function was called.  This is extremely rare,
 +  and generally can only happen during development of Node itself.
 +* `12` **Invalid Debug Argument** - The `--debug` and/or `--debug-brk`
 +  options were set, but an invalid port number was chosen.
 +* `>128` **Signal Exits** - If Node receives a fatal signal such as
 +  `SIGKILL` or `SIGHUP`, then its exit code will be `128` plus the
 +  value of the signal code.  This is a standard Unix practice, since
 +  exit codes are defined to be 7-bit integers, and signal exits set
 +  the high-order bit, and then contain the value of the signal code.
  
  ## Event: 'exit'
  
- Emitted when the process is about to exit.  This is a good hook to perform
- constant time checks of the module's state (like for unit tests).  The main
- event loop will no longer be run after the 'exit' callback finishes, so
- timers may not be scheduled.
+ Emitted when the process is about to exit. There is no way to prevent the
+ exiting of the event loop at this point, and once all `exit` listeners have
+ finished running the process will exit. Therefore you **must** only perform
+ **synchronous** operations in this handler. This is a good hook to perform
+ checks on the module's state (like for unit tests). The callback takes one
+ argument, the code the process is exiting with.
  
  Example of listening for `exit`:
  
-     process.on('exit', function() {
+     process.on('exit', function(code) {
+       // do *NOT* do this
        setTimeout(function() {
          console.log('This will not run');
        }, 0);
-       console.log('About to exit.');
+       console.log('About to exit with code:', code);
      });
  
  ## Event: 'uncaughtException'
@@@ -87,7 -46,7 +90,7 @@@ Example of listening for `uncaughtExcep
      console.log('This will not run.');
  
  Note that `uncaughtException` is a very crude mechanism for exception
 -handling and may be removed in the future.
 +handling.
  
  Don't use it, use [domains](domain.html) instead. If you do use it, restart
  your application after every unhandled exception!
@@@ -304,20 -263,9 +307,20 @@@ To exit with a 'failure' code
  The shell that executed node should see the exit code as 1.
  
  
 +## process.exitCode
 +
 +A number which will be the process exit code, when the process either
 +exits gracefully, or is exited via `process.exit()` without specifying
 +a code.
 +
 +Specifying a code to `process.exit(code)` will override any previous
 +setting of `process.exitCode`.
 +
 +
  ## process.getgid()
  
 -Note: this function is only available on POSIX platforms (i.e. not Windows)
 +Note: this function is only available on POSIX platforms (i.e. not Windows,
 +Android)
  
  Gets the group identity of the process. (See getgid(2).)
  This is the numerical group id, not the group name.
  
  ## process.setgid(id)
  
 -Note: this function is only available on POSIX platforms (i.e. not Windows)
 +Note: this function is only available on POSIX platforms (i.e. not Windows,
 +Android)
  
  Sets the group identity of the process. (See setgid(2).)  This accepts either
  a numerical ID or a groupname string. If a groupname is specified, this method
@@@ -350,8 -297,7 +353,8 @@@ blocks while resolving it to a numerica
  
  ## process.getuid()
  
 -Note: this function is only available on POSIX platforms (i.e. not Windows)
 +Note: this function is only available on POSIX platforms (i.e. not Windows,
 +Android)
  
  Gets the user identity of the process. (See getuid(2).)
  This is the numerical userid, not the username.
  
  ## process.setuid(id)
  
 -Note: this function is only available on POSIX platforms (i.e. not Windows)
 +Note: this function is only available on POSIX platforms (i.e. not Windows,
 +Android)
  
  Sets the user identity of the process. (See setuid(2).)  This accepts either
  a numerical ID or a username string.  If a username is specified, this method
@@@ -384,8 -329,7 +387,8 @@@ blocks while resolving it to a numerica
  
  ## process.getgroups()
  
 -Note: this function is only available on POSIX platforms (i.e. not Windows)
 +Note: this function is only available on POSIX platforms (i.e. not Windows,
 +Android)
  
  Returns an array with the supplementary group IDs. POSIX leaves it unspecified
  if the effective group ID is included but node.js ensures it always is.
  
  ## process.setgroups(groups)
  
 -Note: this function is only available on POSIX platforms (i.e. not Windows)
 +Note: this function is only available on POSIX platforms (i.e. not Windows,
 +Android)
  
  Sets the supplementary group IDs. This is a privileged operation, meaning you
  need to be root or have the CAP_SETGID capability.
@@@ -404,8 -347,7 +407,8 @@@ The list can contain group IDs, group n
  
  ## process.initgroups(user, extra_group)
  
 -Note: this function is only available on POSIX platforms (i.e. not Windows)
 +Note: this function is only available on POSIX platforms (i.e. not Windows,
 +Android)
  
  Reads /etc/group and initializes the group access list, using all groups of
  which the user is a member. This is a privileged operation, meaning you need
@@@ -562,24 -504,14 +565,24 @@@ This will generate
  
  ## process.nextTick(callback)
  
 -On the next loop around the event loop call this callback.
 +* `callback` {Function}
 +
 +Once the current event loop turn runs to completion, call the callback
 +function.
 +
  This is *not* a simple alias to `setTimeout(fn, 0)`, it's much more
 -efficient.  It typically runs before any other I/O events fire, but there
 -are some exceptions.  See `process.maxTickDepth` below.
 +efficient.  It runs before any additional I/O events (including
 +timers) fire in subsequent ticks of the event loop.
  
 +    console.log('start');
      process.nextTick(function() {
        console.log('nextTick callback');
      });
 +    console.log('scheduled');
 +    // Output:
 +    // start
 +    // scheduled
 +    // nextTick callback
  
  This is important in developing APIs where you want to give the user the
  chance to assign event handlers after an object has been constructed,
@@@ -631,10 -563,28 +634,10 @@@ This approach is much better
        fs.stat('file', cb);
      }
  
 -## process.maxTickDepth
 -
 -* {Number} Default = 1000
 -
 -Callbacks passed to `process.nextTick` will *usually* be called at the
 -end of the current flow of execution, and are thus approximately as fast
 -as calling a function synchronously.  Left unchecked, this would starve
 -the event loop, preventing any I/O from occurring.
 -
 -Consider this code:
 -
 -    process.nextTick(function foo() {
 -      process.nextTick(foo);
 -    });
 -
 -In order to avoid the situation where Node is blocked by an infinite
 -loop of recursive series of nextTick calls, it defers to allow some I/O
 -to be done every so often.
 -
 -The `process.maxTickDepth` value is the maximum depth of
 -nextTick-calling nextTick-callbacks that will be evaluated before
 -allowing other forms of I/O to occur.
 +Note: the nextTick queue is completely drained on each pass of the
 +event loop **before** additional I/O is processed.  As a result,
 +recursively setting nextTick callbacks will block any I/O from
 +happening, just like a `while(true);` loop.
  
  ## process.umask([mask])
  
@@@ -675,218 -625,4 +678,218 @@@ a diff reading, useful for benchmarks a
        // benchmark took 1000000527 nanoseconds
      }, 1000);
  
 +
 +## Async Listeners
 +
 +<!-- type=misc -->
 +
 +    Stability: 1 - Experimental
 +
 +The `AsyncListener` API is the JavaScript interface for the `AsyncWrap`
 +class which allows developers to be notified about key events in the
 +lifetime of an asynchronous event. Node performs a lot of asynchronous
 +events internally, and significant use of this API will have a **dramatic
 +performance impact** on your application.
 +
 +
 +## process.createAsyncListener(asyncListener[, callbacksObj[, storageValue]])
 +
 +* `asyncListener` {Function} callback fired when an asynchronous event is
 +instantiated.
 +* `callbacksObj` {Object} optional callbacks that will fire at specific
 +times in the lifetime of the asynchronous event.
 +* `storageValue` {Value} a value that will be passed as the first argument
 +when the `asyncListener` callback is run, and to all subsequent callback.
 +
 +Returns a constructed `AsyncListener` object.
 +
 +To begin capturing asynchronous events pass the object to
 +[`process.addAsyncListener()`][]. The same `AsyncListener` instance can
 +only be added once to the active queue, and subsequent attempts to add the
 +instance will be ignored.
 +
 +To stop capturing pass the object to [`process.removeAsyncListener()`][].
 +This does _not_ mean the `AsyncListener` previously added will stop
 +triggering callbacks. Once attached to an asynchronous event it will
 +persist with the lifetime of the asynchronous call stack.
 +
 +Explanation of function parameters:
 +
 +`asyncListener(storageValue)`: A `Function` called when an asynchronous
 +event is instantiated. If a `Value` is returned then it will be attached
 +to the event and overwrite any value that had been passed to
 +`process.createAsyncListener()`'s `storageValue` argument. If an initial
 +`storageValue` was passed when created, then `asyncListener()` will
 +receive that as a function argument.
 +
 +`callbacksObj`: An `Object` which may contain three optional fields:
 +
 +* `before(context, storageValue)`: A `Function` that is called immediately
 +before the asynchronous callback is about to run. It will be passed both
 +the `context` (i.e. `this`) of the calling function and the `storageValue`
 +either returned from `asyncListener` or passed during construction (if
 +either occurred).
 +
 +* `after(context, storageValue)`: A `Function` called immediately after
 +the asynchronous event's callback has run. Note this will not be called
 +if the callback throws and the error is not handled.
 +
 +* `error(storageValue, error)`: A `Function` called if the event's
 +callback threw. If `error` returns `true` then Node will assume the error
 +has been properly handled and resume execution normally. When multiple
 +`error()` callbacks have been registered, only **one** of those callbacks
 +needs to return `true` for `AsyncListener` to accept that the error has
 +been handled.
 +
 +`storageValue`: A `Value` (i.e. anything) that will be, by default,
 +attached to all new event instances. This will be overwritten if a `Value`
 +is returned by `asyncListener()`.
 +
 +Here is an example of overwriting the `storageValue`:
 +
 +    process.createAsyncListener(function listener(value) {
 +      // value === true
 +      return false;
 +    }, {
 +      before: function before(context, value) {
 +        // value === false
 +      }
 +    }, true);
 +
 +**Note:** The [EventEmitter][], while used to emit status of an asynchronous
 +event, is not itself asynchronous. So `asyncListener()` will not fire when
 +an event is added, and `before`/`after` will not fire when emitted
 +callbacks are called.
 +
 +
 +## process.addAsyncListener(asyncListener[, callbacksObj[, storageValue]])
 +## process.addAsyncListener(asyncListener)
 +
 +Returns a constructed `AsyncListener` object and immediately adds it to
 +the listening queue to begin capturing asynchronous events.
 +
 +Function parameters can either be the same as
 +[`process.createAsyncListener()`][], or a constructed `AsyncListener`
 +object.
 +
 +Example usage for capturing errors:
 +
 +    var cntr = 0;
 +    var key = process.addAsyncListener(function() {
 +      return { uid: cntr++ };
 +    }, {
 +      before: function onBefore(context, storage) {
 +        // Need to remove the listener while logging or will end up
 +        // with an infinite call loop.
 +        process.removeAsyncListener(key);
 +        console.log('uid: %s is about to run', storage.uid);
 +        process.addAsyncListener(key);
 +      },
 +      after: function onAfter(context, storage) {
 +        process.removeAsyncListener(key);
 +        console.log('uid: %s is about to run', storage.uid);
 +        process.addAsyncListener(key);
 +      },
 +      error: function onError(storage, err) {
 +        // Handle known errors
 +        if (err.message === 'really, it\'s ok') {
 +          process.removeAsyncListener(key);
 +          console.log('handled error just threw:');
 +          console.log(err.stack);
 +          process.addAsyncListener(key);
 +          return true;
 +        }
 +      }
 +    });
 +
 +    process.nextTick(function() {
 +      throw new Error('really, it\'s ok');
 +    });
 +
 +    // Output:
 +    // uid: 0 is about to run
 +    // handled error just threw:
 +    // Error: really, it's ok
 +    //     at /tmp/test2.js:27:9
 +    //     at process._tickCallback (node.js:583:11)
 +    //     at Function.Module.runMain (module.js:492:11)
 +    //     at startup (node.js:123:16)
 +    //     at node.js:1012:3
 +
 +## process.removeAsyncListener(asyncListener)
 +
 +Removes the `AsyncListener` from the listening queue.
 +
 +Removing the `AsyncListener` from the queue does _not_ mean asynchronous
 +events called during its execution scope will stop firing callbacks. Once
 +attached to an event it will persist for the entire asynchronous call
 +stack. For example:
 +
 +    var key = process.createAsyncListener(function asyncListener() {
 +      // To log we must stop listening or we'll enter infinite recursion.
 +      process.removeAsyncListener(key);
 +      console.log('You summoned me?');
 +      process.addAsyncListener(key);
 +    });
 +
 +    // We want to begin capturing async events some time in the future.
 +    setTimeout(function() {
 +      process.addAsyncListener(key);
 +
 +      // Perform a few additional async events.
 +      setTimeout(function() {
 +        setImmediate(function() {
 +          process.nextTick(function() { });
 +        });
 +      });
 +
 +      // Removing the listener doesn't mean to stop capturing events that
 +      // have already been added.
 +      process.removeAsyncListener(key);
 +    }, 100);
 +
 +    // Output:
 +    // You summoned me?
 +    // You summoned me?
 +    // You summoned me?
 +    // You summoned me?
 +
 +The fact that we logged 4 asynchronous events is an implementation detail
 +of Node's [Timers][].
 +
 +To stop capturing from a specific asynchronous event stack
 +`process.removeAsyncListener()` must be called from within the call
 +stack itself. For example:
 +
 +    var key = process.createAsyncListener(function asyncListener() {
 +      // To log we must stop listening or we'll enter infinite recursion.
 +      process.removeAsyncListener(key);
 +      console.log('You summoned me?');
 +      process.addAsyncListener(key);
 +    });
 +
 +    // We want to begin capturing async events some time in the future.
 +    setTimeout(function() {
 +      process.addAsyncListener(key);
 +
 +      // Perform a few additional async events.
 +      setImmediate(function() {
 +        // Stop capturing from this call stack.
 +        process.removeAsyncListener(key);
 +
 +        process.nextTick(function() { });
 +      });
 +    }, 100);
 +
 +    // Output:
 +    // You summoned me?
 +
 +The user must be explicit and always pass the `AsyncListener` they wish
 +to remove. It is not possible to simply remove all listeners at once.
 +
 +
  [EventEmitter]: events.html#events_class_events_eventemitter
 +[Timers]: timers.html
 +[`process.createAsyncListener()`]: #process_process_createasynclistener_asynclistener_callbacksobj_storagevalue
 +[`process.addAsyncListener()`]: #process_process_addasynclistener_asynclistener
 +[`process.removeAsyncListener()`]: #process_process_removeasynclistener_asynclistener