-
Notifications
You must be signed in to change notification settings - Fork 336
Description
We ran into an issue where some server instances stopped accepting any requests until our self-host process was restarted. In the Microsoft.Owin trace logs we see the following:
Accept
System.Net.HttpListenerException (0x80004005): An operation was attempted on a nonexistent network connection
at System.Net.HttpListener.EndGetContext(IAsyncResult asyncResult)
at System.Threading.Tasks.TaskFactory`1.FromAsyncCoreLogic(IAsyncResult iar, Func`2 endFunction, Action`1 endAction, Task`1 promise, Boolean requiresSynchronization)
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.Owin.Host.HttpListener.OwinHttpListener.<ProcessRequestsAsync>d__29.MoveNext()
We suspect the problem has been there for years but a specific load pattern at large scale made it worse. Our theory is it's caused by requests with headers greater than 4096 that are immediately abandoned by the client before waiting for response. It's extremely rare but we have 1000+ VMs with 20 billion requests a day so it happens quite regularly for us.
Below is a minimal repro using Microsoft.Owin.SelfHost 4.0.1 with .NET 4.7.2 that forces a HttpListenerException with ErrorCode 1229 "An operation was attempted on a nonexistent network connection" :
namespace OwinSelfHostSample
{
using Microsoft.Owin.Host.HttpListener;
using Microsoft.Owin.Hosting;
using Owin;
using System;
static class Program
{
static void Main()
{
WebApp.Start("http://localhost:8000/", appBuilder =>
{
var owinHttpListener = appBuilder.Properties[typeof(OwinHttpListener).FullName] as OwinHttpListener;
owinHttpListener.SetRequestProcessingLimits(maxAccepts: 1, maxRequests: 1);
appBuilder.Use(async (context, next) => await context.Response.WriteAsync("Hello world!"));
});
Console.ReadKey();
}
}
}- Run program above with .NET source stepping
- Breakpoint on this line: https://referencesource.microsoft.com/#System/net/System/Net/_ListenerAsyncResult.cs,75
- Open browser and go to URL with total request headers >4096 bytes. Here's a sample just with long path and query parameters: http://localhost:8000/some/really/long/path/with/lots/of/query/parameters?value0=0&value1=1&value2=2&value3=3&value4=4&value5=5&value6=6&value7=7&value8=8&value9=9&value10=10&value11=11&value12=12&value13=13&value14=14&value15=15&value16=16&value17=17&value18=18&value19=19&value20=20&value21=21&value22=22&value23=23&value24=24&value25=25&value26=26&value27=27&value28=28&value29=29&value30=30&value31=31&value32=32&value33=33&value34=34&value35=35&value36=36&value37=37&value38=38&value39=39&value40=40&value41=41&value42=42&value43=43&value44=44&value45=45&value46=46&value47=47&value48=48&value49=49&value50=50&value51=51&value52=52&value53=53&value54=54&value55=55&value56=56&value57=57&value58=58&value59=59&value60=60&value61=61&value62=62&value63=63&value64=64&value65=65&value66=66&value67=67&value68=68&value69=69&value70=70&value71=71&value72=72&value73=73&value74=74&value75=75&value76=76&value77=77&value78=78&value79=79&value80=80&value81=81&value82=82&value83=83&value84=84&value85=85&value86=86&value87=87&value88=88&value89=89&value90=90&value91=91&value92=92&value93=93&value94=94&value95=95&value96=96&value97=97&value98=98&value99=99&value100=100&value101=101&value102=102&value103=103&value104=104&value105=105&value106=106&value107=107&value108=108&value109=109&value110=110&value111=111&value112=112&value113=113&value114=114&value115=115&value116=116&value117=117&value118=118&value119=119&value120=120&value121=121&value122=122&value123=123&value124=124&value125=125&value126=126&value127=127&value128=128&value129=129&value130=130&value131=131&value132=132&value133=133&value134=134&value135=135&value136=136&value137=137&value138=138&value139=139&value140=140&value141=141&value142=142&value143=143&value144=144&value145=145&value146=146&value147=147&value148=148&value149=149&value150=150&value151=151&value152=152&value153=153&value154=154&value155=155&value156=156&value157=157&value158=158&value159=159&value160=160&value161=161&value162=162&value163=163&value164=164&value165=165&value166=166&value167=167&value168=168&value169=169&value170=170&value171=171&value172=172&value173=173&value174=174&value175=175&value176=176&value177=177&value178=178&value179=179&value180=180&value181=181&value182=182&value183=183&value184=184&value185=185&value186=186&value187=187&value188=188&value189=189&value190=190&value191=191&value192=192&value193=193&value194=194&value195=195&value196=196&value197=197&value198=198&value199=199&value200=200&value201=201&value202=202&value203=203&value204=204&value205=205&value206=206&value207=207&value208=208&value209=209&value210=210&value211=211&value212=212&value213=213&value214=214&value215=215&value216=216&value217=217&value218=218&value219=219&value220=220&value221=221&value222=222&value223=223&value224=224&value225=225&value226=226&value227=227&value228=228&value229=229&value230=230&value231=231&value232=232&value233=233&value234=234&value235=235&value236=236&value237=237&value238=238&value239=239&value240=240&value241=241&value242=242&value243=243&value244=244&value245=245&value246=246&value247=247&value248=248&value249=249&value250=250&value251=251&value252=252&value253=253&value254=254&value255=255&value256=256&value257=257&value258=258&value259=259&value260=260&value261=261&value262=262&value263=263&value264=264&value265=265&value266=266&value267=267&value268=268&value269=269&value270=270&value271=271&value272=272&value273=273&value274=274&value275=275&value276=276&value277=277&value278=278&value279=279&value280=280&value281=281&value282=282&value283=283&value284=284&value285=285&value286=286&value287=287&value288=288&value289=289&value290=290&value291=291&value292=292&value293=293&value294=294&value295=295&value296=296&value297=297&value298=298&value299=299&value300=300&value301=301&value302=302&value303=303&value304=304&value305=305&value306=306&value307=307&value308=308&value309=309&value310=310&value311=311&value312=312&value313=313&value314=314&value315=315&value316=316&value317=317&value318=318&value319=319&value320=320&value321=321&value322=322&value323=323&value324=324&value325=325&value326=326&value327=327&value328=328&value329=329
- Wait for breakpoint to be hit, then close browser, wait 4 minutes
- Continue from breakpoint,
HttpListenerExceptionwith error code 1229 "An operation was attempted on a nonexistent network connection" will be thrown here: https://referencesource.microsoft.com/#System/net/System/Net/_ListenerAsyncResult.cs,87 OwinHttpListenerthinksHttpListenerhas been disposed when it has not been here: https://github.com/aspnet/AspNetKatana/blob/dev/src/Microsoft.Owin.Host.HttpListener/OwinHttpListener.cs#L226- There are no more accept threads and self-host is effectively dead
We know the error is recoverable as we've added a hack in our service where we have a background thread that periodically checks if there are no accept threads and kicks off a new one using reflection on OwinHttpListener and it works.