You’ll need to see what development has to say. I can’t find record of any stop/quit fix.
I just tried a couple of TrayIcon Quit with 2.1.0.119 (latest Canary), and 2.1.0.5. It took seconds (maybe one or two) for the process to stop, but 2.1.0.5 one time did write out:
C:\Duplicati\duplicati-2.1.0.5_stable_2025-03-04-win-x64-gui\RUN>pause
Press any key to continue . . . Server has started and is listening on port 8005
An error occurred on server tear down: System.ObjectDisposedException: Cannot access a disposed object.
Object name: 'IServiceProvider'.
at Microsoft.Extensions.DependencyInjection.ServiceLookup.ThrowHelper.ThrowObjectDisposedException()
at Microsoft.Extensions.DependencyInjection.ServiceProvider.GetService(ServiceIdentifier serviceIdentifier, ServiceProviderEngineScope serviceProviderEngineScope)
at Microsoft.Extensions.DependencyInjection.ServiceProvider.GetService(Type serviceType)
at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType)
at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService[T](IServiceProvider provider)
at Duplicati.Library.RestAPI.FIXMEGlobal.get_WorkThread()
at Duplicati.Server.Program.<>c.<Main>b__60_12()
at Duplicati.Server.Program.Main(String[] _args)
and new Canary didn’t, but it was not a lot of test samples. I’m not on Linux much, but I did have to do repeated kill on TrayIcon (probably 2.1.0.5) yesterday to finally end process.
I think systemctl goes through a series of steps to try to stop less cooperative processes. There’s documentation somewhere, and journalctl can show log of its actions, such as:
Jun 06 12:40:34 LinuxMint21 duplicati-server[783]: Server has started and is listening on port 8200
Jun 17 14:54:04 LinuxMint21 systemd[1]: Stopping Duplicati web-server...
Jun 17 14:54:15 LinuxMint21 systemd[1]: duplicati.service: State 'stop-sigterm' timed out. Killing.
Jun 17 14:54:15 LinuxMint21 systemd[1]: duplicati.service: Killing process 783 (duplicati-serve) with signal SIGKILL.
Jun 17 14:54:15 LinuxMint21 systemd[1]: duplicati.service: Killing process 1039 (.NET SynchManag) with signal SIGKILL.
Jun 17 14:54:15 LinuxMint21 systemd[1]: duplicati.service: Killing process 1040 (.NET EventPipe) with signal SIGKILL.
Jun 17 14:54:15 LinuxMint21 systemd[1]: duplicati.service: Killing process 1043 (.NET DebugPipe) with signal SIGKILL.
Jun 17 14:54:15 LinuxMint21 systemd[1]: duplicati.service: Killing process 1044 (.NET Debugger) with signal SIGKILL.
Jun 17 14:54:15 LinuxMint21 systemd[1]: duplicati.service: Killing process 1045 (.NET Finalizer) with signal SIGKILL.
Jun 17 14:54:15 LinuxMint21 systemd[1]: duplicati.service: Killing process 1337 (.NET SigHandler) with signal SIGKILL.
Jun 17 14:54:15 LinuxMint21 systemd[1]: duplicati.service: Killing process 1338 (.NET File Watch) with signal SIGKILL.
Jun 17 14:54:15 LinuxMint21 systemd[1]: duplicati.service: Killing process 1339 (.NET Timer) with signal SIGKILL.
Jun 17 14:54:15 LinuxMint21 systemd[1]: duplicati.service: Killing process 1343 (.NET TP Gate) with signal SIGKILL.
Jun 17 14:54:15 LinuxMint21 systemd[1]: duplicati.service: Killing process 1347 (.NET File Watch) with signal SIGKILL.
Jun 17 14:54:15 LinuxMint21 systemd[1]: duplicati.service: Killing process 1361 (Console logger ) with signal SIGKILL.
Jun 17 14:54:15 LinuxMint21 systemd[1]: duplicati.service: Killing process 1404 (.NET Sockets) with signal SIGKILL.
Jun 17 14:54:15 LinuxMint21 systemd[1]: duplicati.service: Killing process 1423 (UpdatePollThrea) with signal SIGKILL.
Jun 17 14:54:15 LinuxMint21 systemd[1]: duplicati.service: Killing process 1424 (WorkerThread<IR) with signal SIGKILL.
Jun 17 14:54:15 LinuxMint21 systemd[1]: duplicati.service: Killing process 1425 (TaskScheduler) with signal SIGKILL.
Jun 17 14:54:15 LinuxMint21 systemd[1]: duplicati.service: Killing process 28702 (.NET TP Worker) with signal SIGKILL.
Jun 17 14:54:15 LinuxMint21 systemd[1]: duplicati.service: Killing process 29730 (.NET TP Worker) with signal SIGKILL.
Jun 17 14:54:15 LinuxMint21 systemd[1]: duplicati.service: Main process exited, code=killed, status=9/KILL
Jun 17 14:54:15 LinuxMint21 systemd[1]: duplicati.service: Failed with result 'timeout'.
Jun 17 14:54:15 LinuxMint21 systemd[1]: Stopped Duplicati web-server.
Jun 17 14:54:15 LinuxMint21 systemd[1]: duplicati.service: Consumed 54.708s CPU time.
EDIT 1:
Linux timing of kill reaction is easier to see with duplicati-server, as prompt returns.
2.1.0.119 with regular kill (SIGTERM) stopped instantly once, then 30 seconds next try:
Server has started and is listening on localhost, port 8200
fail: Microsoft.AspNetCore.Server.Kestrel[13]
Connection id "0HNDEFAPH2U5H", Request id "0HNDEFAPH2U5H:00000001": An unhandled exception was thrown by the application.
Microsoft.AspNetCore.Connections.ConnectionAbortedException: The connection was aborted because the server is shutting down and request processing didn't complete within the time specified by HostOptions.ShutdownTimeout.
at System.IO.Pipelines.Pipe.GetReadResult(ReadResult& result)
at System.IO.Pipelines.Pipe.GetReadAsyncResult()
at System.IO.Pipelines.Pipe.DefaultPipeReader.GetResult(Int16 token)
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.Http1UpgradeMessageBody.ReadAsyncInternalAwaited(ValueTask`1 readTask, CancellationToken cancellationToken)
at System.Runtime.CompilerServices.PoolingAsyncValueTaskMethodBuilder`1.StateMachineBox`1.System.Threading.Tasks.Sources.IValueTaskSource<TResult>.GetResult(Int16 token)
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpRequestStream.ReadAsyncInternal(Memory`1 destination, CancellationToken cancellationToken)
at System.Runtime.CompilerServices.PoolingAsyncValueTaskMethodBuilder`1.StateMachineBox`1.System.Threading.Tasks.Sources.IValueTaskSource<TResult>.GetResult(Int16 token)
at System.IO.Stream.ReadAtLeastAsyncCore(Memory`1 buffer, Int32 minimumBytes, Boolean throwOnEndOfStream, CancellationToken cancellationToken)
at System.Runtime.CompilerServices.PoolingAsyncValueTaskMethodBuilder`1.StateMachineBox`1.System.Threading.Tasks.Sources.IValueTaskSource<TResult>.GetResult(Int16 token)
at System.Net.WebSockets.ManagedWebSocket.EnsureBufferContainsAsync(Int32 minimumRequiredBytes, CancellationToken cancellationToken)
at System.Runtime.CompilerServices.PoolingAsyncValueTaskMethodBuilder`1.StateMachineBox`1.System.Threading.Tasks.Sources.IValueTaskSource.GetResult(Int16 token)
at System.Net.WebSockets.ManagedWebSocket.ReceiveAsyncPrivate[TResult](Memory`1 payloadBuffer, CancellationToken cancellationToken)
at System.Runtime.CompilerServices.PoolingAsyncValueTaskMethodBuilder`1.StateMachineBox`1.System.Threading.Tasks.Sources.IValueTaskSource<TResult>.GetResult(Int16 token)
at System.Threading.Tasks.ValueTask`1.ValueTaskSourceAsTask.<>c.<.cctor>b__4_0(Object state)
--- End of stack trace from previous location ---
at Duplicati.WebserverCore.Notifications.WebsocketAuthenticator.HandleClientData(WebSocket webSocket, CancellationToken cancellationToken)
at Duplicati.WebserverCore.Notifications.WebsocketAuthenticator.AddConnection(WebSocket newConnection)
at Duplicati.WebserverCore.Middlewares.WebsocketExtensions.<>c__DisplayClass0_0.<<UseNotifications>b__0>d.MoveNext()
--- End of stack trace from previous location ---
at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddlewareImpl.<Invoke>g__Awaited|10_0(ExceptionHandlerMiddlewareImpl middleware, HttpContext context, Task task)
at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddlewareImpl.HandleException(HttpContext context, ExceptionDispatchInfo edi)
at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddlewareImpl.<Invoke>g__Awaited|10_0(ExceptionHandlerMiddlewareImpl middleware, HttpContext context, Task task)
at Duplicati.WebserverCore.DuplicatiWebserver.<>c__DisplayClass30_0.<<CreateWebServer>b__10>d.MoveNext()
--- End of stack trace from previous location ---
at Duplicati.WebserverCore.Middlewares.StaticFilesExtensions.<>c__DisplayClass5_0.<<UseDefaultStaticFiles>b__1>d.MoveNext()
--- End of stack trace from previous location ---
at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.ProcessRequests[TContext](IHttpApplication`1 application)
fail: Microsoft.AspNetCore.Server.Kestrel[13]
Connection id "0HNDEFAPH2U5I", Request id "0HNDEFAPH2U5I:00000001": An unhandled exception was thrown by the application.
Microsoft.AspNetCore.Connections.ConnectionAbortedException: The connection was aborted because the server is shutting down and request processing didn't complete within the time specified by HostOptions.ShutdownTimeout.
at System.IO.Pipelines.Pipe.GetReadResult(ReadResult& result)
at System.IO.Pipelines.Pipe.GetReadAsyncResult()
at System.IO.Pipelines.Pipe.DefaultPipeReader.GetResult(Int16 token)
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.Http1UpgradeMessageBody.ReadAsyncInternalAwaited(ValueTask`1 readTask, CancellationToken cancellationToken)
at System.Runtime.CompilerServices.PoolingAsyncValueTaskMethodBuilder`1.StateMachineBox`1.System.Threading.Tasks.Sources.IValueTaskSource<TResult>.GetResult(Int16 token)
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpRequestStream.ReadAsyncInternal(Memory`1 destination, CancellationToken cancellationToken)
at System.Runtime.CompilerServices.PoolingAsyncValueTaskMethodBuilder`1.StateMachineBox`1.System.Threading.Tasks.Sources.IValueTaskSource<TResult>.GetResult(Int16 token)
at System.IO.Stream.ReadAtLeastAsyncCore(Memory`1 buffer, Int32 minimumBytes, Boolean throwOnEndOfStream, CancellationToken cancellationToken)
at System.Runtime.CompilerServices.PoolingAsyncValueTaskMethodBuilder`1.StateMachineBox`1.System.Threading.Tasks.Sources.IValueTaskSource<TResult>.GetResult(Int16 token)
at System.Net.WebSockets.ManagedWebSocket.EnsureBufferContainsAsync(Int32 minimumRequiredBytes, CancellationToken cancellationToken)
at System.Runtime.CompilerServices.PoolingAsyncValueTaskMethodBuilder`1.StateMachineBox`1.System.Threading.Tasks.Sources.IValueTaskSource.GetResult(Int16 token)
at System.Net.WebSockets.ManagedWebSocket.ReceiveAsyncPrivate[TResult](Memory`1 payloadBuffer, CancellationToken cancellationToken)
at System.Runtime.CompilerServices.PoolingAsyncValueTaskMethodBuilder`1.StateMachineBox`1.System.Threading.Tasks.Sources.IValueTaskSource<TResult>.GetResult(Int16 token)
at System.Threading.Tasks.ValueTask`1.ValueTaskSourceAsTask.<>c.<.cctor>b__4_0(Object state)
--- End of stack trace from previous location ---
at Duplicati.WebserverCore.Notifications.WebsocketAuthenticator.HandleClientData(WebSocket webSocket, CancellationToken cancellationToken)
at Duplicati.WebserverCore.Notifications.WebsocketAuthenticator.AddConnection(WebSocket newConnection)
at Duplicati.WebserverCore.Middlewares.WebsocketExtensions.<>c__DisplayClass0_0.<<UseNotifications>b__0>d.MoveNext()
--- End of stack trace from previous location ---
at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddlewareImpl.<Invoke>g__Awaited|10_0(ExceptionHandlerMiddlewareImpl middleware, HttpContext context, Task task)
at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddlewareImpl.HandleException(HttpContext context, ExceptionDispatchInfo edi)
at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddlewareImpl.<Invoke>g__Awaited|10_0(ExceptionHandlerMiddlewareImpl middleware, HttpContext context, Task task)
at Duplicati.WebserverCore.DuplicatiWebserver.<>c__DisplayClass30_0.<<CreateWebServer>b__10>d.MoveNext()
--- End of stack trace from previous location ---
at Duplicati.WebserverCore.Middlewares.StaticFilesExtensions.<>c__DisplayClass5_0.<<UseDefaultStaticFiles>b__1>d.MoveNext()
--- End of stack trace from previous location ---
at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.ProcessRequests[TContext](IHttpApplication`1 application)
As a side note, this topic “Tray icon won’t launch after update” is an odd place for this talk.