-
Notifications
You must be signed in to change notification settings - Fork 4.9k
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
Add reliable timeouts to socket operations #17711
Comments
I just found out that operating systems limit the maximum timeout that is effectively supported. My Windows 7 uses at most 21 seconds and gives up. Web searches show that Linux has a different policy. Therefore, the connect timeout as per this ticket is to be understood as a maximum timeout. This needs to be documented should the feature be added. |
cc: @CIPop @stephentoub |
It may lead to new API proposal. Next steps:
|
Just my 2ct: When there will be finally a
Is this bad practice or problematic in other ways? |
Once we have cancellation based on There is still a need to have timeouts directly supported. Pretty much any application needs to put a timeout on socket operations. I repeat here that all async operations do not respect any configured timeout at the moment. Unfortunately, there are already properties For compatibility reasons we cannot change the fact that async operations do not respect these properties. This means that we need a second way to specify a timeout. It is also problematic, that these properties can only specify an integer number of seconds. Since we are touching these APIs anyway we should allow for more granular timeouts. In my opinion the framework should use
API proposal: We need these timeouts:
I propose adding these on an options object: class SocketTimeouts
{
public TimeSpan? ReceiveTimeout { get; set; }
public TimeSpan? SendTimeout { get; set; }
public TimeSpan? ConnectTimeout { get; set; }
public TimeSpan? AcceptTimeout { get; set; }
public TimeSpan? DiconnectTimeout { get; set; }
}
public SocketTimeouts Timeouts
{
get { return this.timeouts ?? (this.timeouts = new SocketTimeouts()); }
set
{
if (value == null) throw new ArgumentNullException();
this.timeouts = value;
}
} This object can be accessed and set as a whole as I would not touch Alternatives:
|
Cancelling a
With |
triage: we should investigate option for |
Wow this is still a bug in .Net 7. I would have though MS would have removed the API in the .Net 7 release since it STILL doesn't work. I just wasted my morning re-writing my blocking socket code to use the async methods only to find out it's busted after 7 years since the first report of it. Ok I'll just delete the branch I wasted my morning creating. I am specifically trying to shut down a TCP server that is stuck in an AcceptAsync. |
Can you share a repro? The cancellation token passed to AcceptAsync should enable it to be canceled. |
@stephentoub I think possibly this has to do with me pressing Ctrl-C. I have a handler for the event then cancel the tasks, however currently it seems like the TPL just dumps tasks that are running rather than allowing the awaited methods to throw a cancellation event. The debugger then hangs the app. When I run without the debugger the process stops as expected. I'm still debugging now. |
Socket operations do not support timeouts sufficiently in the following cases:
Connect
cannot be made to observe a timeout. I think there is no timeout forAccept
either but that's usually an operation that is never supposed to time out.The workarounds usually are quite nasty. For (1) people build their own (tedious and often flawed) timeouts. For (2) people often use an event plus an async IO. In case the timeout fires they close the socket. (This actually triggers this unavoidable race condition resulting in an access violation!)
Note the amount of confusion that these problems cause: https://www.google.com/webhp?complete=1&hl=en&gws_rd=cr,ssl&ei=#complete=1&hl=en&q=socket+beginreceive+timeout (I sometimes like to point to Google and Stack Overflow to show a nice sample of real-world user complaints. I have opened this ticket because I'm repeatedly facing this issue as well.)
I understand that the underlying Winsock (and now Linux) APIs make some of this hard. Since these issues are so widespread I believe it's worth the work to fix this at the managed code level (by implementing the timeouts and aborts in .NET code as opposed to making the native APIs do that).
As an open concern for (1) I see the question what happens to an IO that is cancelled at the managed level due to timeout or cancellation but still running at the native level. This can cause data to be discarded. The only clean way to solve this that I could find is to terminate the connection when a read or write ends up being cancelled. In my experience this matches perfectly with real world requirements. In case of a timeout usually the calling code backs out and just wants to shut everything down.
To summarize the ticket: Please add timeouts to all possibly blocking socket operations. Related ticket: Allow the user to cancel anything at will (this is needed in addition to the timeout).. Also related: Add Task-based async methods which should take a
CancellationToken
and observe the configured timeout.The text was updated successfully, but these errors were encountered: