Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

IIS App Pool cannot recycle when there is an open ASP.NET 4.5 Websocket

I have run into an issue which can be replicated in the following way (you need IIS8 so must be on Windows 8+ or Windows Server 2012 R2+):

Create a new website in IIS Manager, say TestWs on port 8881, pointing to a new folder, say C:\temp\testws, and add the following Web.config file in 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 in 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 websocket from within the developer toolbar in your browser like so

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

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

However if you create a websocket as described above and go to IIS manager and recycle the application pool, the websocket will not be closed, and there will now be two w3wp.exe processes.

Closing the web socket ws.close(); or refreshing the browser will cause the original w3wp.exe process to be shut down.

It seems the presence of the open websocket is causing IIS to be unable to recycle the app pool correctly.

Can anyone figure out what to change in my code or what to change in IIS to get this to work?

like image 537
Neil Mosafi Avatar asked Dec 10 '14 09:12

Neil Mosafi


1 Answers

As far as I know, while a WebSocket is open, IIS won't tear down the app domain, so you see this behaviour exhibited.

The best I can suggest is that you do some cross process signalling to force the old instance to shutdown. You could achieve this with an EventWaitHandle:

  1. Create a named EventWaitHandle in your web application, and signal it at startup.

  2. On a separate thread, wait on the wait handle

  3. When it is signalled, call HostingEnvironment.InitiateShutdown to force any running old instance to shutdown.

like image 52
chrism Avatar answered Sep 29 '22 14:09

chrism