Make WindowsServiceLifetime gracefully stop (#83892)
authorEric StJohn <ericstj@microsoft.com>
Thu, 6 Apr 2023 04:42:17 +0000 (21:42 -0700)
committerGitHub <noreply@github.com>
Thu, 6 Apr 2023 04:42:17 +0000 (21:42 -0700)
commitf5895b30c56bd3cf0ae82dd88be5e7071d866f9d
tree0a380b8446f2b34bc9720079d3c65a3cd0e89f6f
parent0be7d59945e56187b5ccddec45daed5d8f0840a9
Make WindowsServiceLifetime gracefully stop (#83892)

* Make WindowsServiceLifetime gracefully stop

WindowsServiceLifetime was not waiting for ServiceBase to stop the service.  As a result
we would sometimes end the process before notifying service control manager that the service
had stopped -- resulting in an error in the eventlog and sometimes a service restart.

We also were permitting multiple calls to Stop to occur - through SCM callbacks, and through
public API.  We must not call SetServiceStatus again once the service is marked as stopped.

* Alternate approach to ensuring we only ever set STATE_STOPPED once.

* Avoid calling ServiceBase.Stop on stopped service

I fixed double-calling STATE_STOPPED in ServiceBase, but this fix will
not be present on .NETFramework.  Workaround that by avoiding calling
ServiceBase.Stop when the service has already been stopped by SCM.

* Add tests for WindowsServiceLifetime

These tests leverage RemoteExecutor to avoid creating a separate service
assembly.

* Respond to feedback and add more tests.

This better integrates with the RemoteExecutor component as well,
by hooking up the service process and fetching its handle.

This gives us the correct logging and exitcode handling from
RemoteExecutor.

* Honor Cancellation in StopAsync

* Fix bindingRedirects in RemoteExecutor

* Use Async lambdas for service testing

* Fix issue on Win7 where duplicate service descriptions are disallowed

* Respond to feedback

* Fix comment and add timeout
eng/testing/xunit/xunit.targets
src/libraries/Common/src/Interop/Windows/Advapi32/Interop.QueryServiceStatusEx.cs [new file with mode: 0644]
src/libraries/Common/src/Interop/Windows/Interop.Errors.cs
src/libraries/Microsoft.Extensions.Hosting.WindowsServices/src/WindowsServiceLifetime.cs
src/libraries/Microsoft.Extensions.Hosting.WindowsServices/tests/Microsoft.Extensions.Hosting.WindowsServices.Tests.csproj
src/libraries/Microsoft.Extensions.Hosting.WindowsServices/tests/UseWindowsServiceTests.cs
src/libraries/Microsoft.Extensions.Hosting.WindowsServices/tests/WindowsServiceLifetimeTests.cs [new file with mode: 0644]
src/libraries/Microsoft.Extensions.Hosting.WindowsServices/tests/WindowsServiceTester.cs [new file with mode: 0644]
src/libraries/System.ServiceProcess.ServiceController/src/System/ServiceProcess/ServiceBase.cs