简体   繁体   中英

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

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? Eg 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()

The EBUSY exceptions thrown from KestrelServer.Dispose() will be fixed in the 2.0 release of Kestrel. I think the reason your service is hanging is because _host?.Dispose() is throwing which prevents OnStopped(); from being called inside the OnStop() method.

In the meantime, swallowing the exception to ensure OnStopped(); always gets called should allow the service to be stopped. Make sure to build a new WebHost if you want to restart the server.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM