Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

async_hooks initial implementation #8531

Closed
wants to merge 40 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
5d75ba4
test: remove async_wrap tests
trevnorris Oct 31, 2016
53a85f1
stream_base,tls_wrap: notify on destruct
trevnorris Oct 31, 2016
757ac35
crypto: use named FunctionTemplate
trevnorris Sep 28, 2016
29e9d09
async_wrap: use more specific providers
trevnorris Nov 2, 2016
82d8606
async_wrap: use double, not int64_t, for uid
trevnorris Dec 13, 2016
4a427e3
async_wrap: add GetAsyncId() method
trevnorris Nov 2, 2016
f5d6056
src: add AsyncWrap::GetAsyncId() to all children
trevnorris Sep 28, 2016
1c9154c
async_wrap: only call SetupHooks() once
trevnorris Nov 2, 2016
4c809dd
async_hooks: introduce async_hooks.js
trevnorris Nov 2, 2016
3611f6a
async_hooks: check correct array
trevnorris Nov 17, 2016
d244d55
next_tick: add async_hooks support
trevnorris Nov 14, 2016
977718e
timers: initial timers support
trevnorris Nov 16, 2016
3e5ef64
fs: add initial async_hooks support
trevnorris Nov 17, 2016
955d390
net: add initial async_hooks net support
trevnorris Nov 16, 2016
da7c67c
lib: add triggerId support to various modules
trevnorris Nov 17, 2016
b3721ba
http: reset Agents on free pool
trevnorris Nov 17, 2016
78a2a7f
src: properly propagate triggerId in more places
trevnorris Nov 17, 2016
eab9e86
timers: manually set ids if no hooks exist
trevnorris Nov 18, 2016
4399547
fs: add AsyncReset to TSLWrap
trevnorris Nov 22, 2016
830428a
async_hooks: allow enable/disable while processing
trevnorris Dec 15, 2016
ad382c5
async_hooks: run after() in case of exception
trevnorris Dec 20, 2016
6e5af4a
streams: set initTriggerId before nextTick()
trevnorris Dec 20, 2016
32b5288
next_tick: set MicrotaskCallback to the void
trevnorris Dec 20, 2016
bd660a4
test: allow running with async_hook noops
trevnorris Dec 20, 2016
e8c27f8
async_hooks: move location of restoreTmpHooks()
trevnorris Dec 22, 2016
0ab9547
async_wrap: use v8::Eternal for provider strings
trevnorris Dec 27, 2016
352c89a
fs: use preallocated Float64Array
trevnorris Dec 29, 2016
e9ae576
PARTIAL remove all applicable TODOs
trevnorris Jan 3, 2017
015e665
async_hooks: verify stack integrity
trevnorris Jan 11, 2017
e2af82f
async_hooks: place destroy ids on native list
trevnorris Jan 17, 2017
1b7438f
test: add more async hook tests
trevnorris Jan 17, 2017
ca8d6db
timers: don't reset _asyncId/_triggerId
trevnorris Jan 17, 2017
ac2e137
async_hooks: return early if emitting the void
trevnorris Jan 17, 2017
da138cf
async_hooks: really always exit on exception
trevnorris Jan 18, 2017
25dd8af
async_wrap: don't allow exports to be overwritten
trevnorris Jan 18, 2017
2d98170
fix bug in array buffer size in fs
trevnorris Jan 20, 2017
7bc7d3c
PARTIAL implement new stack tracker
trevnorris Jan 20, 2017
edf67a7
timers: don't emit destroy() on same id twice
trevnorris Jan 26, 2017
90f0a63
test: make async hooks test better
trevnorris Jan 26, 2017
1ff2dfb
async_wrap: print msg on error instead of abort
trevnorris Feb 1, 2017
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions lib/_http_agent.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ const net = require('net');
const util = require('util');
const EventEmitter = require('events');
const debug = util.debuglog('http');
const setInitTriggerId = require('async_hooks').setInitTriggerId;

// New Agent code.

Expand Down Expand Up @@ -72,6 +73,7 @@ function Agent(options) {
self.freeSockets[name] = freeSockets;
socket.setKeepAlive(true, self.keepAliveMsecs);
socket.unref();
socket._asyncId = -1;
socket._httpMessage = null;
self.removeSocket(socket, options);
freeSockets.push(socket);
Expand Down Expand Up @@ -142,6 +144,8 @@ Agent.prototype.addRequest = function addRequest(req, options) {
if (freeLen) {
// we have a free socket, so use that.
var socket = this.freeSockets[name].shift();
// Assign the handle a new asyncId and run any init() hooks.
socket._handle.asyncReset();
debug('have free socket');

// don't leak
Expand All @@ -154,8 +158,11 @@ Agent.prototype.addRequest = function addRequest(req, options) {
} else if (sockLen < this.maxSockets) {
debug('call onSocket', sockLen, freeLen);
// If we are under maxSockets create a new one.
// Agent#addRequest() is only called from the ClientRequest constructor. So
// it's unnecessary to set the parent id before calling createSocket().
this.createSocket(req, options, function(err, newSocket) {
if (err) {
setInitTriggerId(newSocket._handle.getAsyncId());
process.nextTick(function() {
req.emit('error', err);
});
Expand Down Expand Up @@ -269,6 +276,7 @@ Agent.prototype.removeSocket = function removeSocket(s, options) {
// If we have pending requests and a socket gets closed make a new one
this.createSocket(req, options, function(err, newSocket) {
if (err) {
setInitTriggerId(newSocket._handle.getAsyncId());
process.nextTick(function() {
req.emit('error', err);
});
Expand Down
4 changes: 4 additions & 0 deletions lib/_http_client.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ const debug = common.debug;
const OutgoingMessage = require('_http_outgoing').OutgoingMessage;
const Agent = require('_http_agent');
const Buffer = require('buffer').Buffer;
const setInitTriggerId = require('async_hooks').setInitTriggerId;
const urlToOptions = require('internal/url').urlToOptions;

// The actual list of disallowed characters in regexp form is more like:
Expand Down Expand Up @@ -563,6 +564,9 @@ function responseKeepAlive(res, req) {
socket.removeListener('close', socketCloseListener);
socket.removeListener('error', socketErrorListener);
socket.once('error', freeSocketErrorListener);
// There are cases where _handle === null. Avoid those.
if (socket._handle)
setInitTriggerId(socket._handle.getAsyncId());
// Mark this socket as available, AFTER user-added end
// handlers have a chance to run.
process.nextTick(emitFreeNT, socket);
Expand Down
10 changes: 9 additions & 1 deletion lib/_http_common.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ exports.chunkExpression = /(?:^|\W)chunked(?:$|\W)/i;
exports.continueExpression = /(?:^|\W)100-continue(?:$|\W)/i;
exports.methods = methods;

const emitDestroy = require('async_hooks').emitDestroy;

const kOnHeaders = HTTPParser.kOnHeaders | 0;
const kOnHeadersComplete = HTTPParser.kOnHeadersComplete | 0;
const kOnBody = HTTPParser.kOnBody | 0;
Expand Down Expand Up @@ -196,8 +198,14 @@ function freeParser(parser, req, socket) {
parser.incoming = null;
parser.outgoing = null;
parser[kOnExecute] = null;
if (parsers.free(parser) === false)
if (parsers.free(parser) === false) {
parser.close();
} else {
// Since the Parser destructor isn't going to run the destroy() callbacks
// need to be triggered manually.
emitDestroy(parser.getAsyncId());
}
parser = null;
}
if (req) {
req.parser = null;
Expand Down
6 changes: 5 additions & 1 deletion lib/_http_outgoing.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ const Buffer = require('buffer').Buffer;
const common = require('_http_common');
const checkIsHttpToken = common._checkIsHttpToken;
const checkInvalidHeaderChar = common._checkInvalidHeaderChar;
const setInitTriggerId = require('async_hooks').setInitTriggerId;

const CRLF = common.CRLF;
const debug = common.debug;
Expand Down Expand Up @@ -153,8 +154,10 @@ function _writeRaw(data, encoding, callback) {
if (this.output.length) {
this._flushOutput(conn);
} else if (!data.length) {
if (typeof callback === 'function')
if (typeof callback === 'function') {
setInitTriggerId(this.socket._asyncId);
process.nextTick(callback);
}
return true;
}
// Directly write to socket.
Expand Down Expand Up @@ -477,6 +480,7 @@ const crlf_buf = Buffer.from('\r\n');
OutgoingMessage.prototype.write = function write(chunk, encoding, callback) {
if (this.finished) {
var err = new Error('write after end');
setInitTriggerId(this.socket._asyncId);
process.nextTick(writeAfterEndNT, this, err, callback);

return true;
Expand Down
Loading