@@ -66,7 +66,6 @@ public static EmbeddedDatabase Start(EmbeddedDatabaseConfiguration databaseConfi
6666 Logger . InfoFormat ( "Loading RavenDB license from {0}" , licenseFileNameAndServerDirectory . LicenseFileName ) ;
6767 var serverOptions = new ServerOptions
6868 {
69- GracefulShutdownTimeout = TimeSpan . FromHours ( 1 ) , // During Stop/Dispose we manually control this
7069 CommandLineArgs =
7170 [
7271 $ "--Logs.Mode={ databaseConfiguration . LogsMode } ",
@@ -189,30 +188,42 @@ public async Task Stop(CancellationToken cancellationToken)
189188
190189 await shutdownTokenSource . CancelAsync ( ) ;
191190
192- // TODO: await EmbeddedServer.Instance.StopAsync(cancellationToken);
191+ // EmbeddedServer does not have have an async Stop method, the Dispose operation blocks and waits
192+ // until its GracefulShutdownTimeout is reached and then does a Process.Kill
193+ //
194+ // This logic gets the child process ID uses a Task.Delay with infinite.
195+ //
196+ // a. The Task.Delay gets cancelled first
197+ // b. The EmbeddedServer.Dispose completes first
198+ //
199+ // If the Task.Delay gets cancelled first this means Dispose is still running and
200+ // then we kill the process
201+
202+ serverOptions ! . GracefulShutdownTimeout = TimeSpan . FromHours ( 1 ) ; // During Stop/Dispose we manually control this
193203
194204 var processId = await EmbeddedServer . Instance . GetServerProcessIdAsync ( cancellationToken ) ;
195205
206+ // Dispose always need to be invoked, even when already cancelled
207+ var disposeTask = Task . Run ( ( ) => EmbeddedServer . Instance . Dispose ( ) , CancellationToken . None ) ;
208+
196209 var waitForCancellationTask = Task . Delay ( Timeout . Infinite , cancellationToken ) ;
197- var firstTask = await Task . WhenAny (
198- Task . Run ( ( ) => EmbeddedServer . Instance . Dispose ( ) , cancellationToken ) ,
199- waitForCancellationTask
200- ) ;
201210
202- if ( firstTask == waitForCancellationTask )
211+ var delayIsCancelled = waitForCancellationTask == await Task . WhenAny ( disposeTask , waitForCancellationTask ) ;
212+
213+ if ( delayIsCancelled )
203214 {
204215 try
205216 {
206- Logger . WarnFormat ( "Killing RavenDB server PID {0} child process because host cancelled" , processId ) ;
207- var ravenChildProcess = Process . GetProcessById ( processId ) ;
217+ Logger . WarnFormat ( "Killing RavenDB server PID {0} because host cancelled" , processId ) ;
218+ using var ravenChildProcess = Process . GetProcessById ( processId ) ;
208219 ravenChildProcess . Kill ( entireProcessTree : true ) ;
209220 // Kill only signals
210221 Logger . WarnFormat ( "Waiting for RavenDB server PID {0} to exit... " , processId ) ;
211222 await ravenChildProcess . WaitForExitAsync ( CancellationToken . None ) ;
212223 }
213224 catch ( Exception e )
214225 {
215- Logger . ErrorFormat ( "Failed to kill RavenDB server PID {0}\n {1}" , processId , e ) ;
226+ Logger . ErrorFormat ( "Failed to kill RavenDB server PID {0} shutdown \n {1}" , processId , e ) ;
216227 }
217228 }
218229
0 commit comments