Earlier quoted context omitted.
Not really. nginx's implemented behaviour seems more or less what anyone writing socket code would do: write to buffer, then wait with timeout to write more, if timeout is hit consider the write failed. The problem here is that (TIL) on linux the "writable socket" state behaves completely differently than the "readable socket" one, and a socket can be effectively writeable even though poll(2) reports that it isn't.
The TCP layer is already perfectly capable of detecting if a connection has failed. NGINX wanted to do something extra, and did it incorrectly.
The curious case of slow downloads
31–40 of 57 posts
Re: The curious case of slow downloads
#32Earlier quoted context omitted.
What? They wanted a timeout on how long it takes X bytes to send on an active TCP connection. That has nothing to do with poll/select timeouts.
> What? They wanted a timeout on how long it takes X bytes to send on an active TCP connection. That has nothing to do with poll/select timeouts. nginx called send(file), then polled the socket for write with the timeout , closing the connection if the timeout was hit. It has everything to do with poll/select timeouts, and especially with Linux letting poll hit timeouts when waiting on effectively writable sockets.
The goal of NGINX here is not to measure whether a socket can consume any data whatsoever. A connection that consumes 1 byte every 15 seconds is still considered stalled, and should be killed. Using the time between sendfile invocations is not the goal, it's a means toward implementing a minimum rate, and they implemented a minimum rate the wrong way. It's an X Y problem and that's not the kernel's fault.
Re: The curious case of slow downloads
#33I really wish people would stop misusing TCP resets. It's not just a fast way to close a connection. That's not what it's for at all. If you're ever thinking about sending a reset, please read RFC 793 and RFC 3360 first. I'm looking at you Arbor.
Re: The curious case of slow downloads
#34Related story time: At university, we ran a local quakeworld server (yes, this was in the stone age XD). And I wanted to write a tool to allow users to control to server. It would listen on a network port and pipe its input into the quakeworld server running as a child subprocess. Sounds simple enough, right? Disregarding accept(2)ing connections,etc... it's just going to sit in an endless loop, select(2) on the sock…
They should be the ones explaining why they don't have disk quotas set up on a shared system.
Re: The curious case of slow downloads
#35Earlier quoted context omitted.
The TCP layer is already perfectly capable of detecting if a connection has failed. NGINX wanted to do something extra, and did it incorrectly.
> NGINX wanted to do something extra, and did it incorrectly. Having a timeout on a poll (or select) is not "something extra". it's something entirely normal and necessary for any non-trivial software, especially public-facing ones.
Re: The curious case of slow downloads
#36I really wish people would stop misusing TCP resets. It's not just a fast way to close a connection. That's not what it's for at all. If you're ever thinking about sending a reset, please read RFC 793 and RFC 3360 first. I'm looking at you Arbor.
Well the goal here seems to be aborting a connection, not just closing it. They specifically don't want to empty the buffer, because time is up. Is that a misuse of reset?
You can't use a reset just because you want to be fast or don't feel like sending any more data. Resets are for something abnormal happening. A timeout isn't abnormal to a TCP connection. It's part of the process.
Re: The curious case of slow downloads
#37Earlier quoted context omitted.
Well the goal here seems to be aborting a connection, not just closing it. They specifically don't want to empty the buffer, because time is up. Is that a misuse of reset?
Yes, it is a misuse of a TCP reset. The RFCs are very clear about when to use a TCP reset. You can't use a reset just because you want to be fast or don't feel like sending any more data. Resets are for something abnormal happening. A timeout isn't abnormal to a TCP connection. It's part of the process.
Re: The curious case of slow downloads
#38Related story time: At university, we ran a local quakeworld server (yes, this was in the stone age XD). And I wanted to write a tool to allow users to control to server. It would listen on a network port and pipe its input into the quakeworld server running as a child subprocess. Sounds simple enough, right? Disregarding accept(2)ing connections,etc... it's just going to sit in an endless loop, select(2) on the sock…
> Good thing the admins where nice people and didn't shoot me when I went to explain the next monday why the home drive was filled with "blah" XD They should be the ones explaining why they don't have disk quotas set up on a shared system.
But yeah, maybe them being somewhat at fault as well helped me out a bit :)
Re: The curious case of slow downloads
#39Earlier quoted context omitted.
> For example, Microsoft may be changing their image, but their core software is closed source. may be great, but can you pull off something like this when you've got an issue? The importance of being able to debug and patch your mission critical systems is hard to overstate. Not OSS != no source access. A cloud provider on top of the MS stack would most likely have Shared Source Initiative licenses.
Cloudflare was allowed to patch their nginx with the correct solution. Would the Shared Source Initiative allow you to do that, ie patch and run the modified version ?
Licensees may use the source code as a reference or view within a debugger,
but may not modify the code or use it to create derivative works.Re: The curious case of slow downloads
#40Related story time: At university, we ran a local quakeworld server (yes, this was in the stone age XD). And I wanted to write a tool to allow users to control to server. It would listen on a network port and pipe its input into the quakeworld server running as a child subprocess. Sounds simple enough, right? Disregarding accept(2)ing connections,etc... it's just going to sit in an endless loop, select(2) on the sock…
Read will return 0 when the peer has closed the connection, that's how you detect it. When there is no data, the call will block instead until some data arrives (unless the socket is set to non-block mode).