-
Notifications
You must be signed in to change notification settings - Fork 30k
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
net: server.maxConnections does not trigger error on some platforms #1885
Comments
FWIW that test also broke ARM, SmartOS and Windows, it isn't just FreeBSD. |
Here is a refined test case that illustrates the bug. For me it always fails on FreeBSD 10.0 amd64, and does not on OSX 10.10.3. var net = require('net');
var server = net.createServer();
// Hack to reject all connections
server.maxConnections = -1;
// Listen, connect (closed asap), but write in between.
server.listen(9876, function() {
console.error('connecting');
var connection = net.connect(9876, function() {
var buffered = this.write('foo');
console.error('sent message, data', buffered ? 'flushed' : 'queued');
});
connection.on('close', function() {
server.close();
console.error('this run did not error and die');
});
}); Non-error run (OSX @ v2.2.1):
Error run (FreeBSD @ 43a82f8):
The error is emitted on the client connection. I think what is happening here is, since I think this is a bug on the platforms that fail with |
I installed FreeBSD 10.1 on VirtualBox on my Mac and am unable to replicate this either with the test code above or by reverting So, flying somewhat blind because I am unable to replicate the problem (any assistance welcome) even though I have no doubt the problem is very real... Likely relevant for any archeology on this:
Maybe @brendanashworth or @santigimeno (or someone else running a version of FreeBSD that exhibits this issue) can compile with that line changed to Not sure if this is a case of "oh well, different operating systems will behave differently" or if there's a good reason to attempt a workaround. For what it's worth, it looks like ruby may have implemented a workaround specifically for this. |
@Trott fwiw I use the FreeBSD in https://github.com/brendanashworth/vms, just run I think you should follow up what you're looking at and try your idea. That ruby patch looks like it's related, or at least feels like it. Too bad it doesn't mention any of the other OSs. cc: @bnoordhuis for the earlier commit |
Thanks, @brendanashworth. That worked for replicating the problem. And the change I suggested "solves" it but, you know, might break other tests. ( |
This may be getting off the trail here, but hey @brendanashworth, when you set up your FreeBSD 10.0 via Vagrant with OS X as the host OS, does this succeed for you?
If not, does applying these two changes fix it?
|
Doesn't work for me in the suite or individually. And not temp file related. So not #1876-related, I don't think. Either way, if It's Just Me, then maybe I ought to just blow everything away, start over, and see if it goes away... |
Bumping my VM from 1 CPU to 2 CPUs and fixed the |
Er...um...OK...bumping myself from 1 CPU to 2 CPUs also made the test case above start passing for me on FreeBSD. Er...@brendanashworth, do you experience that too? Or is the test still failing for you on FreeBSD if you go from (presumably) a single CPU to 2? |
@Trott erm. that fixes it. perhaps it is related to how libuv handles writes on various platforms async/sync? this made the bug twice as weird. |
I've run the test from @brendanashworth and it always fails in my FreeBSD box.
After the server closes the connection |
Disregard the last comment, I don't think there should be an error emitted. |
Perhaps |
It feels to me like a libuv issue - but it looks to be the same as libuv/libuv#45, which was closed as "not a libuv issue". Perhaps take a look here too. |
There is a tiny platform-specific workaround libuv could do here (squelch the ECONNRESET if EV_EOF is set) but that won't work on all platforms. |
On various platforms, behaviour in return values differs on the read(2) syscall. On OSX (+ others), read() on a closed-ish socket will return an EOF, while on FreeBSD (+ others), read() on the same closed-ish socket will emit an ECONNRESET error. This commit swallows the ECONNRESET error on the offending platforms to instead emit an EOF, allowing behaviour to be consistent between platforms. Ref: nodejs/node#1885
@bnoordhuis taking a look, I think it could work on all platforms, but please correct me if I'm wrong.
OSX:
FreeBSD:
Even though our friend from 2005 wasn't quite clear on his documentation, the behavior seems to show that FreeBSD tends toward the If we apply this patch to the io.js tree, we can escape the diff --git a/deps/uv/src/unix/stream.c b/deps/uv/src/unix/stream.c
index 7ad1658..73ec0cf 100644
--- a/deps/uv/src/unix/stream.c
+++ b/deps/uv/src/unix/stream.c
@@ -1139,6 +1139,9 @@ static void uv__read(uv_stream_t* stream) {
uv__stream_osx_interrupt_select(stream);
}
stream->read_cb(stream, 0, &buf);
+ } else if (errno == ECONNRESET) {
+ uv__stream_eof(stream, &buf);
} else {
/* Error. User should call uv_close(). */
stream->read_cb(stream, -errno, &buf); With that patch, all You can view the full commit here: brendanashworth/libuv@a302dda. cc @saghul, would libuv be okay in carrying a patch like that? |
@brendanashworth I don;t think I like that approach. EOF means the connection was closed cleanly, as in all data was read. If the application which calls close sets SO_LINGER with timeout 0, for example, ECONNRESET is produced on the other side, and we cannot be sure if they read all the data we sent. Squelching it where possible, if EOF was already set, as @bnoordhuis pointed out here: #1885 (comment) could help, but I'm -1 on the general case. |
What @saghul said, it would hide real connection reset errors. I think checking for EV_EOF (or EPOLLRDHUP on Linux) is the best libuv can do here. |
I have given this a try: santigimeno/libuv@3e5eeb9 . Does it make any sense? I'm not familiar with libuv internals. It fixes the test case for me in FreeBSD but some libuv tests don't look good. |
PR here : libuv/libuv#403 updated with @bnoordhuis comments |
The patch has landed: libuv/libuv@05a003a. |
Notice that it solves the issue on FreeBSD but not on Windows |
Patch first available here: #2310 |
I see a libuv patch landed but was then reverted. There hasn't been any comments on this issue in nearly two years. Does anyone know if it's still an issue? Should it be closed? Or perhaps updated? |
I'm going to close this dormant issue that I originally opened 2.5 years ago. 😮 It's not clear to me that it's a bug as opposed to a timing issue. No one seems to be actively working on it nor does it seem to be affecting users. |
(Of course, if you think I'm wrong to close it, re-open if GitHub lets you, or leave a comment indicating that you believe it should be re-opened.) |
See #1881 for discussion and some details. Exceeding
server.maxConnections
on OS X (andprobablyothers) does not trigger ECONNRESET(at least in some situations) but it seemingly shouldand it does on FreeBSD(and probably others).The text was updated successfully, but these errors were encountered: