Tmds.DBus icon indicating copy to clipboard operation
Tmds.DBus copied to clipboard

Deadlock on disposing signal subscriptions

Open M0ns1gn0r opened this issue 3 months ago • 1 comments

Hi, we're using the following interface:

[DBusInterface("de.pengutronix.rauc.Installer")]
interface IRauc : IDBusObject
{
    Task InstallAsync(string Source);
    Task<(string compatible, string version)> InfoAsync(string Bundle);
    Task<(string slotName, string message)> MarkAsync(string State, string SlotIdentifier);
    Task<(string, IDictionary<string, object>)[]> GetSlotStatusAsync();
    Task<string> GetPrimaryAsync();
    Task<IDisposable> WatchCompletedAsync(Action<int> handler, Action<Exception> onError = null);
    Task<T> GetAsync<T>(string prop);
    Task<RaucProperties> GetAllAsync();
    Task SetAsync(string prop, object val);
    Task<IDisposable> WatchPropertiesAsync(Action<PropertyChanges> handler);
}

Here is how we use that IRauc raucClient:

public async Task InstallUpdate(string raucbPath)
{
    var installCompletion = new TaskCompletionSource<int>(TaskCreationOptions.RunContinuationsAsynchronously);

    using var completionWatch = await raucClient.WatchCompletedAsync(
        r => installCompletion.TrySetResult(r),
        ex => installCompletion.TrySetException(ex));

    using var progressWatch = await raucClient.WatchPropertiesAsync(changes => ...logging and processing it...);

    await raucClient.InstallAsync(raucbPath);

    var returnCode = await installCompletion.Task;
    if (returnCode != 0)
    {
        throw new RaucUpdateFailedException($"InstallAsync failed, return code: {returnCode}.");
    }
}

By the nature of using operator, completionWatch and progressWatch are getting disposed at the end of InstallUpdate method. One in ~10 calls to InstallUpdate ends up in a deadlock :(

image

We would be very grateful if you could investigate and fix this.

M0ns1gn0r avatar Apr 30 '24 15:04 M0ns1gn0r