Compare commits

...

3 Commits

Author SHA1 Message Date
isaacs
55ddf54adf 2012.08.03 Version 0.6.21 (maintenance)
* sunos: work around OS bug to prevent fs.watch() from spinning (Bryan Cantrill)

* net: make pause/resume work with connecting sockets (Bert Belder)
2012-08-03 14:39:24 -07:00
Ben Noordhuis
974ee7b3ec deps: upgrade libuv to d6a96de 2012-08-03 16:08:35 +02:00
Bert Belder
7d7bca6493 net: make pause/resume work with connecting sockets
Calling resume() on a net connection for which the IP address is still
being resolved crashes node with an assertion error inside libuv.
Calling pause() before the socket is connected doesn't crash, but it
doesn't work either. This patch fixes it.

Ref: #3118
2012-08-03 15:48:29 +02:00
5 changed files with 134 additions and 11 deletions

View File

@@ -1,4 +1,11 @@
2012.07.10 Version 0.6.20 (maintenance)
2012.08.03 Version 0.6.21 (maintenance)
* sunos: work around OS bug to prevent fs.watch() from spinning (Bryan Cantrill)
* net: make pause/resume work with connecting sockets (Bert Belder)
2012.07.10 Version 0.6.20 (maintenance), 952e513379169ec1b40909d1db056e9bf4294899
* npm: Upgrade to 1.1.37 (isaacs)

View File

@@ -110,7 +110,7 @@ static void uv__fs_event_rearm(uv_fs_event_t *handle) {
static void uv__fs_event_read(EV_P_ ev_io* w, int revents) {
uv_fs_event_t *handle;
uv_fs_event_t *handle = NULL;
uv_loop_t *loop_;
timespec_t timeout;
port_event_t pe;
@@ -120,15 +120,25 @@ static void uv__fs_event_read(EV_P_ ev_io* w, int revents) {
loop_ = container_of(w, uv_loop_t, fs_event_watcher);
do {
/* TODO use port_getn() */
uint_t n = 1;
/*
* Note that our use of port_getn() here (and not port_get()) is deliberate:
* there is a bug in event ports (Sun bug 6456558) whereby a zeroed timeout
* causes port_get() to return success instead of ETIME when there aren't
* actually any events (!); by using port_getn() in lieu of port_get(),
* we can at least workaround the bug by checking for zero returned events
* and treating it as we would ETIME.
*/
do {
memset(&timeout, 0, sizeof timeout);
r = port_get(loop_->fs_fd, &pe, &timeout);
r = port_getn(loop_->fs_fd, &pe, 1, &n, &timeout);
}
while (r == -1 && errno == EINTR);
if (r == -1 && errno == ETIME)
if ((r == -1 && errno == ETIME) || n == 0)
break;
handle = (uv_fs_event_t *)pe.portev_user;
assert((r == 0) && "unexpected port_get() error");
@@ -143,7 +153,7 @@ static void uv__fs_event_read(EV_P_ ev_io* w, int revents) {
}
while (handle->fd != PORT_DELETED);
if (handle->fd != PORT_DELETED)
if (handle != NULL && handle->fd != PORT_DELETED)
uv__fs_event_rearm(handle);
}

View File

@@ -83,6 +83,7 @@ function initSocketHandle(self) {
self._flags = 0;
self._connectQueueSize = 0;
self._paused = false;
self.destroyed = false;
self.errorEmitted = false;
self.bytesRead = 0;
@@ -201,8 +202,10 @@ Object.defineProperty(Socket.prototype, 'bufferSize', {
Socket.prototype.pause = function() {
this._paused = true;
if (this._handle) {
this._handle.readStop();
if (!this._connecting) this._handle.readStop();
// this adds an undesireable boundary crossing for pipe streams.
// the .unref() method is omitted on TCP streams, because it is
@@ -213,8 +216,10 @@ Socket.prototype.pause = function() {
Socket.prototype.resume = function() {
this._paused = false;
if (this._handle) {
this._handle.readStart();
if (!this._connecting) this._handle.readStart();
// this adds an undesireable boundary crossing for pipe streams.
// the .ref() method is omitted on TCP streams, because it is
@@ -636,7 +641,7 @@ function afterConnect(status, handle, req, readable, writable) {
self.writable = writable;
timers.active(self);
if (self.readable) {
if (self.readable && !self._paused) {
handle.readStart();
}
@@ -867,7 +872,7 @@ function onconnection(clientHandle) {
});
socket.readable = socket.writable = true;
socket.resume();
clientHandle.readStart();
self.connections++;
socket.server = self;

View File

@@ -29,7 +29,7 @@
#define NODE_MAJOR_VERSION 0
#define NODE_MINOR_VERSION 6
#define NODE_PATCH_VERSION 21
#define NODE_VERSION_IS_RELEASE 0
#define NODE_VERSION_IS_RELEASE 1
#ifndef NODE_STRINGIFY
#define NODE_STRINGIFY(n) NODE_STRINGIFY_HELPER(n)

View File

@@ -0,0 +1,101 @@
// Copyright Joyent, Inc. and other Node contributors.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to permit
// persons to whom the Software is furnished to do so, subject to the
// following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
// USE OR OTHER DEALINGS IN THE SOFTWARE.
var common = require('../common'),
assert = require('assert'),
net = require('net');
var connections = 0,
dataEvents = 0,
conn;
// Server
var server = net.createServer(function(conn) {
connections++;
conn.end('This was the year he fell to pieces.');
if (connections === 5)
server.close();
});
server.listen(common.PORT);
// Client 1
conn = require('net').createConnection(common.PORT, 'localhost');
conn.resume();
conn.on('data', onDataOk);
// Client 2
conn = require('net').createConnection(common.PORT, 'localhost');
conn.pause();
conn.resume();
conn.on('data', onDataOk);
// Client 3
conn = require('net').createConnection(common.PORT, 'localhost');
conn.pause();
conn.on('data', onDataError);
scheduleTearDown(conn);
// Client 4
conn = require('net').createConnection(common.PORT, 'localhost');
conn.resume();
conn.pause();
conn.resume();
conn.on('data', onDataOk);
// Client 5
conn = require('net').createConnection(common.PORT, 'localhost');
conn.resume();
conn.resume();
conn.pause();
conn.on('data', onDataError);
scheduleTearDown(conn);
// Client helper functions
function onDataError() {
assert(false);
}
function onDataOk() {
dataEvents++;
}
function scheduleTearDown(conn) {
setTimeout(function() {
conn.removeAllListeners('data');
conn.resume();
}, 100);
}
// Exit sanity checks
process.on('exit', function() {
assert.strictEqual(connections, 5);
assert.strictEqual(dataEvents, 3);
});