| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 7e3a3c9 commit 4a7233c
13 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -25,6 +25,8 @@ const net = require('net'); | |||
| 25 | 25 | const util = require('util'); | |
| 26 | 26 | const EventEmitter = require('events'); | |
| 27 | 27 | const debug = util.debuglog('http'); | |
| 28 | + const async_id_symbol = process.binding('async_wrap').async_id_symbol; | ||
| 29 | + const nextTick = require('internal/process/next_tick').nextTick; | ||
| 28 | 30 | ||
| 29 | 31 | // New Agent code. | |
| 30 | 32 | ||
@@ -93,6 +95,7 @@ function Agent(options) { | |||
| 93 | 95 | self.freeSockets[name] = freeSockets; | |
| 94 | 96 | socket.setKeepAlive(true, self.keepAliveMsecs); | |
| 95 | 97 | socket.unref(); | |
| 98 | + socket[async_id_symbol] = -1; | ||
| 96 | 99 | socket._httpMessage = null; | |
| 97 | 100 | self.removeSocket(socket, options); | |
| 98 | 101 | freeSockets.push(socket); | |
@@ -163,6 +166,8 @@ Agent.prototype.addRequest = function addRequest(req, options, port/*legacy*/, | |||
| 163 | 166 | if (freeLen) { | |
| 164 | 167 | // we have a free socket, so use that. | |
| 165 | 168 | var socket = this.freeSockets[name].shift(); | |
| 169 | + // Assign the handle a new asyncId and run any init() hooks. | ||
| 170 | + socket._handle.asyncReset(); | ||
| 166 | 171 | debug('have free socket'); | |
| 167 | 172 | ||
| 168 | 173 | // don't leak | |
@@ -177,7 +182,7 @@ Agent.prototype.addRequest = function addRequest(req, options, port/*legacy*/, | |||
| 177 | 182 | // If we are under maxSockets create a new one. | |
| 178 | 183 | this.createSocket(req, options, function(err, newSocket) { | |
| 179 | 184 | if (err) { | |
| 180 | - process.nextTick(function() { | ||
| 185 | + nextTick(newSocket._handle.getAsyncId(), function() { | ||
| 181 | 186 | req.emit('error', err); | |
| 182 | 187 | }); | |
| 183 | 188 | return; | |
@@ -290,7 +295,7 @@ Agent.prototype.removeSocket = function removeSocket(s, options) { | |||
| 290 | 295 | // If we have pending requests and a socket gets closed make a new one | |
| 291 | 296 | this.createSocket(req, options, function(err, newSocket) { | |
| 292 | 297 | if (err) { | |
| 293 | - process.nextTick(function() { | ||
| 298 | + nextTick(newSocket._handle.getAsyncId(), function() { | ||
| 294 | 299 | req.emit('error', err); | |
| 295 | 300 | }); | |
| 296 | 301 | return; | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -36,6 +36,7 @@ const Agent = require('_http_agent'); | |||
| 36 | 36 | const Buffer = require('buffer').Buffer; | |
| 37 | 37 | const urlToOptions = require('internal/url').urlToOptions; | |
| 38 | 38 | const outHeadersKey = require('internal/http').outHeadersKey; | |
| 39 | + const nextTick = require('internal/process/next_tick').nextTick; | ||
| 39 | 40 | ||
| 40 | 41 | // The actual list of disallowed characters in regexp form is more like: | |
| 41 | 42 | // /[^A-Za-z0-9\-._~!$&'()*+,;=/:@]/ | |
@@ -587,9 +588,12 @@ function responseKeepAlive(res, req) { | |||
| 587 | 588 | socket.removeListener('close', socketCloseListener); | |
| 588 | 589 | socket.removeListener('error', socketErrorListener); | |
| 589 | 590 | socket.once('error', freeSocketErrorListener); | |
| 591 | + // There are cases where _handle === null. Avoid those. Passing null to | ||
| 592 | + // nextTick() will call initTriggerId() to retrieve the id. | ||
| 593 | + const asyncId = socket._handle ? socket._handle.getAsyncId() : null; | ||
| 590 | 594 | // Mark this socket as available, AFTER user-added end | |
| 591 | 595 | // handlers have a chance to run. | |
| 592 | - process.nextTick(emitFreeNT, socket); | ||
| 596 | + nextTick(asyncId, emitFreeNT, socket); | ||
| 593 | 597 | } | |
| 594 | 598 | } | |
| 595 | 599 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -28,6 +28,7 @@ const HTTPParser = binding.HTTPParser; | |||
| 28 | 28 | const FreeList = require('internal/freelist'); | |
| 29 | 29 | const ondrain = require('internal/http').ondrain; | |
| 30 | 30 | const incoming = require('_http_incoming'); | |
| 31 | + const emitDestroy = require('async_hooks').emitDestroy; | ||
| 31 | 32 | const IncomingMessage = incoming.IncomingMessage; | |
| 32 | 33 | const readStart = incoming.readStart; | |
| 33 | 34 | const readStop = incoming.readStop; | |
@@ -211,8 +212,13 @@ function freeParser(parser, req, socket) { | |||
| 211 | 212 | parser.incoming = null; | |
| 212 | 213 | parser.outgoing = null; | |
| 213 | 214 | parser[kOnExecute] = null; | |
| 214 | - if (parsers.free(parser) === false) | ||
| 215 | + if (parsers.free(parser) === false) { | ||
| 215 | 216 | parser.close(); | |
| 217 | + } else { | ||
| 218 | + // Since the Parser destructor isn't going to run the destroy() callbacks | ||
| 219 | + // it needs to be triggered manually. | ||
| 220 | + emitDestroy(parser.getAsyncId()); | ||
| 221 | + } | ||
| 216 | 222 | } | |
| 217 | 223 | if (req) { | |
| 218 | 224 | req.parser = null; | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -31,6 +31,8 @@ const common = require('_http_common'); | |||
| 31 | 31 | const checkIsHttpToken = common._checkIsHttpToken; | |
| 32 | 32 | const checkInvalidHeaderChar = common._checkInvalidHeaderChar; | |
| 33 | 33 | const outHeadersKey = require('internal/http').outHeadersKey; | |
| 34 | + const async_id_symbol = process.binding('async_wrap').async_id_symbol; | ||
| 35 | + const nextTick = require('internal/process/next_tick').nextTick; | ||
| 34 | 36 | ||
| 35 | 37 | const CRLF = common.CRLF; | |
| 36 | 38 | const debug = common.debug; | |
@@ -264,8 +266,9 @@ function _writeRaw(data, encoding, callback) { | |||
| 264 | 266 | if (this.output.length) { | |
| 265 | 267 | this._flushOutput(conn); | |
| 266 | 268 | } else if (!data.length) { | |
| 267 | - if (typeof callback === 'function') | ||
| 268 | - process.nextTick(callback); | ||
| 269 | + if (typeof callback === 'function') { | ||
| 270 | + nextTick(this.socket[async_id_symbol], callback); | ||
| 271 | + } | ||
| 269 | 272 | return true; | |
| 270 | 273 | } | |
| 271 | 274 | // Directly write to socket. | |
@@ -623,7 +626,10 @@ const crlf_buf = Buffer.from('\r\n'); | |||
| 623 | 626 | OutgoingMessage.prototype.write = function write(chunk, encoding, callback) { | |
| 624 | 627 | if (this.finished) { | |
| 625 | 628 | var err = new Error('write after end'); | |
| 626 | - process.nextTick(writeAfterEndNT.bind(this), err, callback); | ||
| 629 | + nextTick(this.socket[async_id_symbol], | ||
| 630 | + writeAfterEndNT.bind(this), | ||
| 631 | + err, | ||
| 632 | + callback); | ||
| 627 | 633 | ||
| 628 | 634 | return true; | |
| 629 | 635 | } | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -32,7 +32,7 @@ var processing_hook = false; | |||
| 32 | 32 | // Use to temporarily store and updated active_hooks_array if the user enables | |
| 33 | 33 | // or disables a hook while hooks are being processed. | |
| 34 | 34 | var tmp_active_hooks_array = null; | |
| 35 | - // Keep track of the field counds held in tmp_active_hooks_array. | ||
| 35 | + // Keep track of the field counts held in tmp_active_hooks_array. | ||
| 36 | 36 | var tmp_async_hook_fields = null; | |
| 37 | 37 | ||
| 38 | 38 | // Each constant tracks how many callbacks there are for any given step of | |
@@ -41,9 +41,9 @@ var tmp_async_hook_fields = null; | |||
| 41 | 41 | const { kInit, kBefore, kAfter, kDestroy, kCurrentAsyncId, kCurrentTriggerId, | |
| 42 | 42 | kAsyncUidCntr, kInitTriggerId } = async_wrap.constants; | |
| 43 | 43 | ||
| 44 | + const { async_id_symbol, trigger_id_symbol } = async_wrap; | ||
| 45 | + | ||
| 44 | 46 | // Used in AsyncHook and AsyncEvent. | |
| 45 | - const async_id_symbol = Symbol('_asyncId'); | ||
| 46 | - const trigger_id_symbol = Symbol('_triggerId'); | ||
| 47 | 47 | const init_symbol = Symbol('init'); | |
| 48 | 48 | const before_symbol = Symbol('before'); | |
| 49 | 49 | const after_symbol = Symbol('after'); | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -25,7 +25,10 @@ const assert = require('assert'); | |||
| 25 | 25 | const Buffer = require('buffer').Buffer; | |
| 26 | 26 | const util = require('util'); | |
| 27 | 27 | const EventEmitter = require('events'); | |
| 28 | + const setInitTriggerId = require('async_hooks').setInitTriggerId; | ||
| 28 | 29 | const UV_UDP_REUSEADDR = process.binding('constants').os.UV_UDP_REUSEADDR; | |
| 30 | + const async_id_symbol = process.binding('async_wrap').async_id_symbol; | ||
| 31 | + const nextTick = require('internal/process/next_tick').nextTick; | ||
| 29 | 32 | ||
| 30 | 33 | const UDP = process.binding('udp_wrap').UDP; | |
| 31 | 34 | const SendWrap = process.binding('udp_wrap').SendWrap; | |
@@ -111,6 +114,7 @@ function Socket(type, listener) { | |||
| 111 | 114 | this._handle = handle; | |
| 112 | 115 | this._receiving = false; | |
| 113 | 116 | this._bindState = BIND_STATE_UNBOUND; | |
| 117 | + this[async_id_symbol] = this._handle.getAsyncId(); | ||
| 114 | 118 | this.type = type; | |
| 115 | 119 | this.fd = null; // compatibility hack | |
| 116 | 120 | ||
@@ -432,6 +436,10 @@ function doSend(ex, self, ip, list, address, port, callback) { | |||
| 432 | 436 | req.callback = callback; | |
| 433 | 437 | req.oncomplete = afterSend; | |
| 434 | 438 | } | |
| 439 | + // node::SendWrap isn't instantiated and attached to the JS instance of | ||
| 440 | + // SendWrap above until send() is called. So don't set the init trigger id | ||
| 441 | + // until now. | ||
| 442 | + setInitTriggerId(self[async_id_symbol]); | ||
| 435 | 443 | var err = self._handle.send(req, | |
| 436 | 444 | list, | |
| 437 | 445 | list.length, | |
@@ -441,7 +449,7 @@ function doSend(ex, self, ip, list, address, port, callback) { | |||
| 441 | 449 | if (err && callback) { | |
| 442 | 450 | // don't emit as error, dgram_legacy.js compatibility | |
| 443 | 451 | const ex = exceptionWithHostPort(err, 'send', address, port); | |
| 444 | - process.nextTick(callback, ex); | ||
| 452 | + nextTick(self[async_id_symbol], callback, ex); | ||
| 445 | 453 | } | |
| 446 | 454 | } | |
| 447 | 455 | ||
@@ -468,7 +476,7 @@ Socket.prototype.close = function(callback) { | |||
| 468 | 476 | this._stopReceiving(); | |
| 469 | 477 | this._handle.close(); | |
| 470 | 478 | this._handle = null; | |
| 471 | - process.nextTick(socketCloseNT, this); | ||
| 479 | + nextTick(this[async_id_symbol], socketCloseNT, this); | ||
| 472 | 480 | ||
| 473 | 481 | return this; | |
| 474 | 482 | }; | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -292,10 +292,20 @@ | |||
| 292 | 292 | } | |
| 293 | 293 | ||
| 294 | 294 | function setupProcessFatal() { | |
| 295 | + const async_wrap = process.binding('async_wrap'); | ||
| 296 | + // Arrays containing hook flags and ids for async_hook calls. | ||
| 297 | + const { async_hook_fields, async_uid_fields } = async_wrap; | ||
| 298 | + // Internal functions needed to manipulate the stack. | ||
| 299 | + const { clearIdStack, popAsyncIds } = async_wrap; | ||
| 300 | + const { kAfter, kCurrentAsyncId, kInitTriggerId } = async_wrap.constants; | ||
| 295 | 301 | ||
| 296 | 302 | process._fatalException = function(er) { | |
| 297 | 303 | var caught; | |
| 298 | 304 | ||
| 305 | + // It's possible that kInitTriggerId was set for a constructor call that | ||
| 306 | + // threw and was never cleared. So clear it now. | ||
| 307 | + async_uid_fields[kInitTriggerId] = 0; | ||
| 308 | + | ||
| 299 | 309 | if (process.domain && process.domain._errorHandler) | |
| 300 | 310 | caught = process.domain._errorHandler(er); | |
| 301 | 311 | ||
@@ -314,9 +324,21 @@ | |||
| 314 | 324 | // nothing to be done about it at this point. | |
| 315 | 325 | } | |
| 316 | 326 | ||
| 317 | - // if we handled an error, then make sure any ticks get processed | ||
| 318 | 327 | } else { | |
| 328 | + // If we handled an error, then make sure any ticks get processed | ||
| 319 | 329 | NativeModule.require('timers').setImmediate(process._tickCallback); | |
| 330 | + | ||
| 331 | + // Emit the after() hooks now that the exception has been handled. | ||
| 332 | + if (async_hook_fields[kAfter] > 0) { | ||
| 333 | + do { | ||
| 334 | + NativeModule.require('async_hooks').emitAfter( | ||
| 335 | + async_uid_fields[kCurrentAsyncId]); | ||
| 336 | + // popAsyncIds() returns true if there are more ids on the stack. | ||
| 337 | + } while (popAsyncIds(async_uid_fields[kCurrentAsyncId])); | ||
| 338 | + // Or completely empty the id stack. | ||
| 339 | + } else { | ||
| 340 | + clearIdStack(); | ||
| 341 | + } | ||
| 320 | 342 | } | |
| 321 | 343 | ||
| 322 | 344 | return caught; | |
| Back | FazBrowse Home | New Git URL |
0 commit comments