Unable to stop asp.net core Windows Service when Kestrel receives requests

Viewed 2356

We are using asp.net core running on .net 4.5.1 as Windows Service. Kestrel is used as web server (Kestrel version is 1.1.2). It was configured in accordance with Host an ASP.NET Core app in a Windows Service. We also using SignalR running on OWIN.

The problem occurs when two events occur simultaneously: Windows Service is stopping and some new web requests were received by Krestel. If these conditions are met, then Windows service stops responding and hangs.

Windows could not stop the Topshelf.Host service on Local Computer. Error 1061: The service cannot accept control messages at this time.

Confuguration code:

var port = Global.Settings.Port;
var hostBuilder = new WebHostBuilder()                  
                .UseKestrel()                   
                .UseStartup<Startup>()
                .UseUrls("http://+:" + port);

if (runAsService)
 {                    
       hostBuilder.UseContentRoot(directoryPath);
       Directory.SetCurrentDirectory(directoryPath);
 }
 else
 {                    
     hostBuilder.UseContentRoot(Directory.GetCurrentDirectory());
 }

var host = hostBuilder.Build();
if (runAsService)
{                 
    host.RunAsCustomService();
}
else
{                    
      host.Run();
}

public static class WebHostServiceExtensions
{
    public static void RunAsCustomService(this IWebHost host)
    {
        var webHostService = new CustomWebHostService(host);
        ServiceBase.Run(webHostService);
    }
}
internal class CustomWebHostService : WebHostService
{
    public CustomWebHostService(IWebHost host) : base(host)
    {
    }

//...
}

Further investigation revealed that unhandled exception occured when disposing _host in WebHostService.cs.

protected sealed override void OnStop()
{
    _stopRequestedByWindows = true;
    OnStopping();
    _host?.Dispose();
    OnStopped();
}

As described below, it raises an exception "Microsoft.AspNetCore.Server.Kestrel.Internal.Networking.UvException: Error -4082 EBUSY resource busy or locked"

The Question is:

Is there a way to avoid such an error and prevent Windows Service hangs? E.g. stop Krestel before _host disposing or prevent new incoming connection in OnStopping event.

Stacktrace:

Microsoft.AspNetCore.Server.Kestrel.Internal.Networking.UvException: Error -4082 EBUSY resource busy or locked
in Microsoft.AspNetCore.Server.Kestrel.Internal.Networking.Libuv.loop_close(UvLoopHandle handle) in Microsoft.AspNetCore.Server.Kestrel.Internal.Networking.UvLoopHandle.ReleaseHandle() in System.Runtime.InteropServices.SafeHandle.InternalDispose() in System.Runtime.InteropServices.SafeHandle.Dispose(Boolean disposing)
in System.Runtime.InteropServices.SafeHandle.Dispose() in Microsoft.AspNetCore.Server.Kestrel.Internal.KestrelThread.ThreadStart(Object parameter)

in Microsoft.AspNetCore.Server.Kestrel.Internal.KestrelThread.d__51.MoveNext() in System.Threading.Tasks.Task.WaitAll(Task[] tasks, Int32 millisecondsTimeout, CancellationToken cancellationToken) in Microsoft.AspNetCore.Server.Kestrel.Internal.KestrelEngine.Dispose()
in Microsoft.AspNetCore.Server.Kestrel.KestrelServer.Dispose() in Microsoft.Extensions.DependencyInjection.ServiceProvider.Dispose()
in Microsoft.AspNetCore.Hosting.Internal.WebHost.Dispose()

Microsoft.AspNetCore.Server.Kestrel.Internal.Networking.UvException: Error -4082 EBUSY resource busy or locked in Microsoft.AspNetCore.Server.Kestrel.Internal.Networking.Libuv.loop_close(UvLoopHandle handle) in Microsoft.AspNetCore.Server.Kestrel.Internal.Networking.UvLoopHandle.ReleaseHandle() in System.Runtime.InteropServices.SafeHandle.InternalDispose() in System.Runtime.InteropServices.SafeHandle.Dispose(Boolean disposing)
in System.Runtime.InteropServices.SafeHandle.Dispose() in Microsoft.AspNetCore.Server.Kestrel.Internal.KestrelThread.ThreadStart(Object parameter)

в Microsoft.AspNetCore.Server.Kestrel.Internal.KestrelThread.d__51.MoveNext()

1 Answers
Related