| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent a7596d7 commit c60857a
4 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -57,7 +57,7 @@ Worker.prototype.isConnected = function isConnected() { | |||
| 57 | 57 | ||
| 58 | 58 | // Master/worker specific methods are defined in the *Init() functions. | |
| 59 | 59 | ||
| 60 | - function SharedHandle(key, address, port, addressType, backlog, fd) { | ||
| 60 | + function SharedHandle(key, address, port, addressType, backlog, fd, flags) { | ||
| 61 | 61 | this.key = key; | |
| 62 | 62 | this.workers = []; | |
| 63 | 63 | this.handle = null; | |
@@ -66,7 +66,7 @@ function SharedHandle(key, address, port, addressType, backlog, fd) { | |||
| 66 | 66 | // FIXME(bnoordhuis) Polymorphic return type for lack of a better solution. | |
| 67 | 67 | var rval; | |
| 68 | 68 | if (addressType === 'udp4' || addressType === 'udp6') | |
| 69 | - rval = dgram._createSocketHandle(address, port, addressType, fd); | ||
| 69 | + rval = dgram._createSocketHandle(address, port, addressType, fd, flags); | ||
| 70 | 70 | else | |
| 71 | 71 | rval = net._createServerHandle(address, port, addressType, fd); | |
| 72 | 72 | ||
@@ -438,7 +438,8 @@ function masterInit() { | |||
| 438 | 438 | var args = [message.address, | |
| 439 | 439 | message.port, | |
| 440 | 440 | message.addressType, | |
| 441 | - message.fd]; | ||
| 441 | + message.fd, | ||
| 442 | + message.index]; | ||
| 442 | 443 | var key = args.join(':'); | |
| 443 | 444 | var handle = handles[key]; | |
| 444 | 445 | if (handle === undefined) { | |
@@ -456,7 +457,8 @@ function masterInit() { | |||
| 456 | 457 | message.port, | |
| 457 | 458 | message.addressType, | |
| 458 | 459 | message.backlog, | |
| 459 | - message.fd); | ||
| 460 | + message.fd, | ||
| 461 | + message.flags); | ||
| 460 | 462 | } | |
| 461 | 463 | if (!handle.data) handle.data = message.data; | |
| 462 | 464 | ||
@@ -485,7 +487,7 @@ function masterInit() { | |||
| 485 | 487 | cluster.emit('listening', worker, info); | |
| 486 | 488 | } | |
| 487 | 489 | ||
| 488 | - // Round-robin only. Server in worker is closing, remove from list. | ||
| 490 | + // Server in worker is closing, remove from list. | ||
| 489 | 491 | function close(worker, message) { | |
| 490 | 492 | var key = message.key; | |
| 491 | 493 | var handle = handles[key]; | |
@@ -500,6 +502,7 @@ function masterInit() { | |||
| 500 | 502 | ||
| 501 | 503 | function workerInit() { | |
| 502 | 504 | var handles = {}; | |
| 505 | + var indexes = {}; | ||
| 503 | 506 | ||
| 504 | 507 | // Called from src/node.js | |
| 505 | 508 | cluster._setupWorker = function() { | |
@@ -528,15 +531,22 @@ function workerInit() { | |||
| 528 | 531 | }; | |
| 529 | 532 | ||
| 530 | 533 | // obj is a net#Server or a dgram#Socket object. | |
| 531 | - cluster._getServer = function(obj, address, port, addressType, fd, cb) { | ||
| 532 | - var message = { | ||
| 533 | - addressType: addressType, | ||
| 534 | - address: address, | ||
| 535 | - port: port, | ||
| 534 | + cluster._getServer = function(obj, options, cb) { | ||
| 535 | + const key = [ options.address, | ||
| 536 | + options.port, | ||
| 537 | + options.addressType, | ||
| 538 | + options.fd ].join(':'); | ||
| 539 | + if (indexes[key] === undefined) | ||
| 540 | + indexes[key] = 0; | ||
| 541 | + else | ||
| 542 | + indexes[key]++; | ||
| 543 | + | ||
| 544 | + const message = util._extend({ | ||
| 536 | 545 | act: 'queryServer', | |
| 537 | - fd: fd, | ||
| 546 | + index: indexes[key], | ||
| 538 | 547 | data: null | |
| 539 | - }; | ||
| 548 | + }, options); | ||
| 549 | + | ||
| 540 | 550 | // Set custom data on handle (i.e. tls tickets key) | |
| 541 | 551 | if (obj._getServerData) message.data = obj._getServerData(); | |
| 542 | 552 | send(message, function(reply, handle) { | |
@@ -549,9 +559,9 @@ function workerInit() { | |||
| 549 | 559 | }); | |
| 550 | 560 | obj.once('listening', function() { | |
| 551 | 561 | cluster.worker.state = 'listening'; | |
| 552 | - var address = obj.address(); | ||
| 562 | + const address = obj.address(); | ||
| 553 | 563 | message.act = 'listening'; | |
| 554 | - message.port = address && address.port || port; | ||
| 564 | + message.port = address && address.port || options.port; | ||
| 555 | 565 | send(message); | |
| 556 | 566 | }); | |
| 557 | 567 | }; | |
@@ -563,6 +573,7 @@ function workerInit() { | |||
| 563 | 573 | // closed. Avoids resource leaks when the handle is short-lived. | |
| 564 | 574 | var close = handle.close; | |
| 565 | 575 | handle.close = function() { | |
| 576 | + send({ act: 'close', key: key }); | ||
| 566 | 577 | delete handles[key]; | |
| 567 | 578 | return close.apply(this, arguments); | |
| 568 | 579 | }; | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -60,14 +60,14 @@ function newHandle(type) { | |||
| 60 | 60 | } | |
| 61 | 61 | ||
| 62 | 62 | ||
| 63 | - exports._createSocketHandle = function(address, port, addressType, fd) { | ||
| 63 | + exports._createSocketHandle = function(address, port, addressType, fd, flags) { | ||
| 64 | 64 | // Opening an existing fd is not supported for UDP handles. | |
| 65 | 65 | assert(typeof fd !== 'number' || fd < 0); | |
| 66 | 66 | ||
| 67 | 67 | var handle = newHandle(addressType); | |
| 68 | 68 | ||
| 69 | 69 | if (port || address) { | |
| 70 | - var err = handle.bind(address, port || 0, 0); | ||
| 70 | + var err = handle.bind(address, port || 0, flags); | ||
| 71 | 71 | if (err) { | |
| 72 | 72 | handle.close(); | |
| 73 | 73 | return err; | |
@@ -176,8 +176,12 @@ Socket.prototype.bind = function(port /*, address, callback*/) { | |||
| 176 | 176 | if (!cluster) | |
| 177 | 177 | cluster = require('cluster'); | |
| 178 | 178 | ||
| 179 | + var flags = 0; | ||
| 180 | + if (self._reuseAddr) | ||
| 181 | + flags |= constants.UV_UDP_REUSEADDR; | ||
| 182 | + | ||
| 179 | 183 | if (cluster.isWorker && !exclusive) { | |
| 180 | - cluster._getServer(self, ip, port, self.type, -1, function(err, handle) { | ||
| 184 | + function onHandle(err, handle) { | ||
| 181 | 185 | if (err) { | |
| 182 | 186 | var ex = exceptionWithHostPort(err, 'bind', ip, port); | |
| 183 | 187 | self.emit('error', ex); | |
@@ -191,16 +195,19 @@ Socket.prototype.bind = function(port /*, address, callback*/) { | |||
| 191 | 195 | ||
| 192 | 196 | replaceHandle(self, handle); | |
| 193 | 197 | startListening(self); | |
| 194 | - }); | ||
| 198 | + } | ||
| 199 | + cluster._getServer(self, { | ||
| 200 | + address: ip, | ||
| 201 | + port: port, | ||
| 202 | + addressType: self.type, | ||
| 203 | + fd: -1, | ||
| 204 | + flags: flags | ||
| 205 | + }, onHandle); | ||
| 195 | 206 | ||
| 196 | 207 | } else { | |
| 197 | 208 | if (!self._handle) | |
| 198 | 209 | return; // handle has been closed in the mean time | |
| 199 | 210 | ||
| 200 | - var flags = 0; | ||
| 201 | - if (self._reuseAddr) | ||
| 202 | - flags |= constants.UV_UDP_REUSEADDR; | ||
| 203 | - | ||
| 204 | 211 | var err = self._handle.bind(ip, port || 0, flags); | |
| 205 | 212 | if (err) { | |
| 206 | 213 | var ex = exceptionWithHostPort(err, 'bind', ip, port); | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1268,7 +1268,13 @@ function listen(self, address, port, addressType, backlog, fd, exclusive) { | |||
| 1268 | 1268 | return; | |
| 1269 | 1269 | } | |
| 1270 | 1270 | ||
| 1271 | - cluster._getServer(self, address, port, addressType, fd, cb); | ||
| 1271 | + cluster._getServer(self, { | ||
| 1272 | + address: address, | ||
| 1273 | + port: port, | ||
| 1274 | + addressType: addressType, | ||
| 1275 | + fd: fd, | ||
| 1276 | + flags: 0 | ||
| 1277 | + }, cb); | ||
| 1272 | 1278 | ||
| 1273 | 1279 | function cb(err, handle) { | |
| 1274 | 1280 | // EADDRINUSE may not be reported until we call listen(). To complicate | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,40 @@ | |||
| 1 | + 'use strict'; | ||
| 2 | + const common = require('../common'); | ||
| 3 | + const assert = require('assert'); | ||
| 4 | + const cluster = require('cluster'); | ||
| 5 | + const dgram = require('dgram'); | ||
| 6 | + | ||
| 7 | + if (common.isWindows) { | ||
| 8 | + console.log('1..0 # Skipped: dgram clustering is currently not supported ' + | ||
| 9 | + 'on windows.'); | ||
| 10 | + return; | ||
| 11 | + } | ||
| 12 | + | ||
| 13 | + if (cluster.isMaster) { | ||
| 14 | + cluster.fork().on('exit', function(code) { | ||
| 15 | + assert.equal(code, 0); | ||
| 16 | + }); | ||
| 17 | + return; | ||
| 18 | + } | ||
| 19 | + | ||
| 20 | + const sockets = []; | ||
| 21 | + function next() { | ||
| 22 | + sockets.push(this); | ||
| 23 | + if (sockets.length !== 2) | ||
| 24 | + return; | ||
| 25 | + | ||
| 26 | + // Work around health check issue | ||
| 27 | + process.nextTick(function() { | ||
| 28 | + for (var i = 0; i < sockets.length; i++) | ||
| 29 | + sockets[i].close(close); | ||
| 30 | + }); | ||
| 31 | + } | ||
| 32 | + | ||
| 33 | + var waiting = 2; | ||
| 34 | + function close() { | ||
| 35 | + if (--waiting === 0) | ||
| 36 | + cluster.worker.disconnect(); | ||
| 37 | + } | ||
| 38 | + | ||
| 39 | + for (var i = 0; i < 2; i++) | ||
| 40 | + dgram.createSocket({ type: 'udp4', reuseAddr: true }).bind(common.PORT, next); | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments