-
Notifications
You must be signed in to change notification settings - Fork 1.3k
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
Socket disconnects when payload timeout is false #3099
Comments
The |
In that case the problem is even worse because sending data does not keep the socket open. (hapi 13.2.1 and node 4.2.6) |
I wrote a script to verify. Check it out at: For the following configuration:
Output: |
It appears that the socket timeout behavior is bugged (at least for http-based sockets) on the current node releases. I will try to investigate further. |
Here's a script that emulates the issue you're seeing without any hapi stuff: const Http = require('http');
const server = Http.createServer((req, res) => {
req.socket.setTimeout(100); // there shouldn't be 100ms of 'inactivity' because we write every 10ms
req.pipe(process.stdout);
req.on('end', () => {
res.end('hiii');
});
});
server.listen(4052, (err) => {
if (err) {
throw err;
}
console.log('Listening!');
const req = Http.request({
hostname: 'localhost',
port: 4052,
path: '/',
method: 'POST'
}, (res) => {});
const interval = setInterval(() => {
req.write('a');
}, 10);
req.on('error', (err) => {
console.log(err);
clearInterval(interval);
server.close();
});
}); Console:
|
I ran this above across a few Node versions: No error in node v0.10.43, v0.12.2 |
Node seems to set its own timeout on HTTP sockets, the fix seems to be to remove Node's own listener when adding yours: const server = Http.createServer((req, res) => {
req.socket.removeAllListeners('timeout'); // remove node's default listener
req.socket.setTimeout(100); // there shouldn't be 100ms of 'inactivity' because we write every 10ms
req.pipe(process.stdout);
req.on('end', () => {
res.end('hiii');
});
}); hapi should probably do something similar if this isn't working properly. |
@mtharrison That won't work. You just removed the close behavior on timeouts. |
Basically, what happens is that http requests hide the actual transmission from the socket, which means that the activity tracking code is never called (intentionally or not). In any case, node either has a bug or incorrect documentation. FYI, I found nodejs/node#3319 which seems to be about this issue. Edit: I'm leaning towards an implementation bug in node. |
Yeah, I was being lazy and not really testing my idea. Good find on the above ^^ |
I ran a test script with |
@mtharrison I was just about to suggest that commit as the root cause 😃 From nodejs/node#2355 |
Nice, I left a comment over there. I guess either way it's a bug in node's code/docs or some behaviour change needed in hapi. |
NodeJS also are mentioning in the documentation that by default the socket timeout is never, which obviously is not the case. |
@shugigo The default is changed since it is from a http server connection. See https://nodejs.org/api/http.html#http_server_timeout. |
Looks like a fix is incoming for Node: nodejs/node#6286 |
The fix for this has landed: Node 4.4.5: nodejs/node#6824 Data flowing on the socket will now reset the timeout. Confirmed my test case above works now in both versions, so closing this issue. |
ECONNRESET Error: Client request error: socket hang up
In route config, when { payload: { timeout: false }} (never) the socket will timeout after 2 minutes (node default).
To fix this problem { timeout: { socket : false } } must be specified.
I expected that the socket timeout config will automatically be the size of the payload timeout.
Route validation will catch similar problems, for example:
When payload timeout is specified in milliseconds ({ payload: { timeout: 240000 }}) the server will throw if the timeout is greater than socket timeout (if specified or not).
Route validation should fail if { payload: { timeout: false} } and { timeout: { socket: 120000 }}
or
Socket timeout should automatically be set to payload timeout.
The text was updated successfully, but these errors were encountered: