IIS application pool cannot be recycled when there is an open ASP.NET 4.5 Web site

I am having a problem that can be replicated as follows (you need IIS8, so it should be on Windows 8+ or Windows Server 2012 R2 +):

Create a new website in IIS Manager, say TestWs on port 8881, point to the new folder, say C: \ temp \ testws, and add the following Web.config file there.

<?xml version="1.0"?> <configuration> <system.web> <compilation targetFramework="4.5"/> <httpRuntime targetFramework="4.5"/> </system.web> </configuration> 

Now add the following WsHandler.ashx file to the same folder

 <%@ WebHandler Language="C#" Class="WsHandler" %> using System; using System.Threading; using System.Web; public class WsHandler : IHttpHandler { public void ProcessRequest(HttpContext context) { context.AcceptWebSocketRequest(async webSocketContext => { while (true) { await webSocketContext.WebSocket.ReceiveAsync(new ArraySegment<byte>(new byte[1024]), CancellationToken.None); } }); } public bool IsReusable { get { return true; } } } 

Then create a website from the developer toolbar in your browser, for example:

 var ws = new WebSocket("ws://localhost:8881/wshandler.ashx"); ws.onclose = function() { console.log('closed'); }; 

In the task manager, you will see that for this application there is a w3wp.exe process, if you kill it, the client will receive the onclose event, and closed text will be printed.

However, if you create the website as described above and go to IIS Manager and restart the application pool, the website will not be closed, and now there will be two w3wp.exe processes.

Closing the web socket ws.close(); or updating the browser will disable the original w3wp.exe process.

It seems that the presence of an open websocket means that IIS will not be able to properly utilize the application pool.

Can someone figure out what to change in my code or what to change in IIS to make this work?

+7
iis websocket
source share
3 answers

As far as I know, while WebSocket is open, IIS does not break the application domain, so you can see that this behavior is manifest.

The best I can offer is that you do some cross-process signaling to make the old instance shut down. You can achieve this with EventWaitHandle :

+4
source share

Try setting “Shutdown time limit” to 1 second (application pool> Advanced settings> Process model) [PS: I do not have IIS8. I am checking properties in IIS7.]

This property determines the time set for the workflow to complete request processing and shut down. If the workflow exceeds the completion time limit, it ends.

I see that the default value in IIS7 is 90 seconds. If this is the same value in IIS8 too, then it can give a lot of time to the previous workflow to finish the job. After 90 seconds (1.5 minutes), it will stop this process and your web socket will be closed. If you change it for 1 second, it will terminate the previous workflow, which will be broken almost instantly (as soon as you process the application pool), and you will get the expected behavior.

+3
source share

Since I had the same problem, here is the solution I found out:

In your IHttpHandler you should have a static object that inherits IStopListeningRegisteredObject. Then use HostingEnvironment.RegisterObject (this) to get notified (via StopListening) when the application pool is redistributed.

You will also need the CancellationTokenSource file (static, too), which you will pass to ReceiveAsync. In StopListening (), you can use Cancel () for the CancellationTokenSource to end the wait. Then catch an OperationCanceledException and call Abort () on the socket.

Don't forget that Dispose () after Cancel () or the App-Pool will still wait.

0
source share

All Articles