-
Notifications
You must be signed in to change notification settings - Fork 29.8k
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 setTimeout behaviour not working as expected for HTTP requests #5899
Comments
edit: closed the other issue as this one has more detail. |
cc @nodejs/http |
+1 |
Confirmed, caused by stream consumption indeed. Working on a fix, thanks! |
When underlying `net.Socket` instance is consumed in http server - no `data` events are emitted, and thus `socket.setTimeout` fires the callback even if the data is constantly flowing into the socket. Fix this by calling `socket._unrefTimer()` on every `onParserExecute` call. Fix: nodejs#5899
Fix #6286 |
When underlying `net.Socket` instance is consumed in http server - no `data` events are emitted, and thus `socket.setTimeout` fires the callback even if the data is constantly flowing into the socket. Fix this by calling `socket._unrefTimer()` on every `onParserExecute` call. Fix: #5899 PR-URL: #6286 Reviewed-By: James M Snell <[email protected]>
When underlying `net.Socket` instance is consumed in http server - no `data` events are emitted, and thus `socket.setTimeout` fires the callback even if the data is constantly flowing into the socket. Fix this by calling `socket._unrefTimer()` on every `onParserExecute` call. Fix: #5899 PR-URL: #6286 Reviewed-By: James M Snell <[email protected]>
When underlying `net.Socket` instance is consumed in http server - no `data` events are emitted, and thus `socket.setTimeout` fires the callback even if the data is constantly flowing into the socket. Fix this by calling `socket._unrefTimer()` on every `onParserExecute` call. Fix: nodejs#5899 PR-URL: nodejs#6286 Reviewed-By: James M Snell <[email protected]>
When underlying `net.Socket` instance is consumed in http server - no `data` events are emitted, and thus `socket.setTimeout` fires the callback even if the data is constantly flowing into the socket. Fix this by calling `socket._unrefTimer()` on every `onParserExecute` call. Fix: #5899 PR-URL: #6286 Reviewed-By: James M Snell <[email protected]>
I met the same issue with node-v0.10.36, should I upgrade the node to solve this problem? Any other ideas? |
Yes. This likely won't make it back to the 0.10 release line. |
@baolinCloud node-v0.10 doesn't include the initial commit 607bbd3 that introduced the regression. lib/http.js hasn't changed on things related to timeout since before this regression commit: https://github.com/nodejs/node/commits/v0.10/lib/http.js So I think this bug is not present in node v0.10. |
nodejs v4.4.4 was released after this fix landed on master, but didn't include this fix. When will this be released in v4.x ? This is a severe regression for all users of setTimeout. |
v4.4.4 was intentionally limited to a smaller set of security related fixes. I imagine this can hit in v4.4.5. /cc @thealphanerd |
I just push this change to Expect an rc later today and a release next week |
When underlying `net.Socket` instance is consumed in http server - no `data` events are emitted, and thus `socket.setTimeout` fires the callback even if the data is constantly flowing into the socket. Fix this by calling `socket._unrefTimer()` on every `onParserExecute` call. Fix: #5899 PR-URL: #6286 Reviewed-By: James M Snell <[email protected]>
When underlying `net.Socket` instance is consumed in http server - no `data` events are emitted, and thus `socket.setTimeout` fires the callback even if the data is constantly flowing into the socket. Fix this by calling `socket._unrefTimer()` on every `onParserExecute` call. Fix: #5899 PR-URL: #6286 Reviewed-By: James M Snell <[email protected]>
@triccardi-systran My test code is simple: var http = require('http'); server = http.createServer(function (request, response) { When I use postman to get from http://127.0.0.1:1337 , I get the response of 'Hello World'. But also log 'timeout'. My node version is 0.10.36. Any thing is wrong with my code? I just want to set timeout to less than 2min. |
@baolinCloud I think that's expected behaviour. You responded and ended the first request in the 200ms timeout, then the socket (still connected because of Keep-Alive) times out. If you just want to change the timeout on the server to less than 2 min use var http = require('http');
server = http.createServer(function (request, response) {
// set to more than 200ms and no response will come back because of timeout
setTimeout(function() {
response.writeHead(200, {'Content-Type': 'text/plain'});
response.end('Hello World\n');
}, 200);
}).listen(1337, '127.0.0.1');
server.setTimeout(500); |
@mtharrison I want to catch the timeout event and response a specified message. For example, if time out , log the event and response 'hello'. Otherwise, response 'HELLO'. And I don not want to log timeout if not timeout. In fact I always get the timeout log whether timeout or not. Any ideas ? |
This seems to happen again in node 14. Really bad behavior. Uploads stop at about 1m with ECONNRESET |
@matthiasg You should open a new issue with details. |
Summary
timeout
events are fired on sockets assigned to an HTTP request even when there is activity (data being written) within the timeout period. This is unexpected and not explicitly documented.This did not used to be the case, it used to work like a normal
net
socket, with the timeout being essentially "reset" on any activity. The behaviour changed after this commit 607bbd3 without any obvious doc changes.Full background
A TCP (
net
) socket has asetTimeout
method which sets the socket to emit atimeout
event after a certain number of ms of inactivity. This currently works correctly on all tested versions. An example is below:There’s also a setTimeout method available on a HTTP request which proxies the
setTimeout
call through to the underlying TCP socket. So I expected it to work the same. But it does not, it will timeout even when data is being written actively to the socket.It was an issue posted at hapijs/hapi#3099 that led me to this digging. I used the script above to
git bisect
the Node core repo back to the commit where the behaviour changed 607bbd3 which is part of PR #2355.Conclusion
I think this is either a bug or If the new behaviour is intended, a documentation update is probably needed to explicitly state that the timeout on an
http
socket works differently than a regularnet
socket.The text was updated successfully, but these errors were encountered: