0

Well, I'll try to explain my situation as far as I could detail it. I'm trying to make compatible a third-party repository that can be used to download addons on the Steam workshop (it's called DepotDownloader managed by SteamRE).

The problem is that when I step-over the debugger gets lost and doesn't recover over the next line.

I already resolved one issue, as you can see here:

https://github.com/uta-org/DepotDownloader/commit/a935e90f4d7713700734fb9fc551cf50f51ca264

I'll try to comply with a Minimal, Complete, and Verifiable example. For it, you'll need to clone it with:

$ git clone -b uzsourcetoolkit https://github.com/uta-org/DepotDownloader.git

On a fresh Unity3D project (I'm currently using 2019.4.0.f1).

The following code is the one that I'm using to debug the code:

using System;
using System.ComponentModel;
using System.Threading;
using DepotDownloader;
using UnityEngine;

public class DepotTester : MonoBehaviour
{
    public object Target { get; }

    public event Action<ulong, ulong> DownloadProgressChanged = delegate { };

    public event Action<object, byte[]> DownloadCompleted = delegate { };

    public void UnloadEvents()
    {
    }

    public void DownloadDataAsync(ulong fromWhere)
    {
        // ReSharper disable once PossibleInvalidCastException
        //new Thread(ContentDownloader.DownloadPubfileAsync(fromWhere).GetAwaiter().GetResult).Start();

        ContentDownloader.DownloadPubfileAsync(fromWhere).GetAwaiter().GetResult();
    }

    private void OnDownloadProgressChanged(ulong bytesReceived, ulong totalBytesToReceive)
    {
        DownloadProgressChanged(bytesReceived, totalBytesToReceive);
    }

    private void OnDownloadDataCompleted(byte[] result)
    {
        DownloadCompleted(null, result);
    }

    private void Awake()
    {
        if (ContentDownloader.IsInitialized)
            return;

        string[] args = new string[0];
        ContentDownloader.Config.InstallDirectory = GetParameter<string>(args, "-dir");

        ContentDownloader.Config.VerifyAll = HasParameter(args, "-verify-all") ||
                                             HasParameter(args, "-verify_all") || HasParameter(args, "-validate");
        ContentDownloader.Config.MaxServers = GetParameter(args, "-max-servers", 20);
        ContentDownloader.Config.MaxDownloads = GetParameter(args, "-max-downloads", 4);
        ContentDownloader.Config.MaxServers = Math.Max(ContentDownloader.Config.MaxServers,
            ContentDownloader.Config.MaxDownloads);
        ContentDownloader.Config.LoginID =
            HasParameter(args, "-loginid") ? (uint?)GetParameter<uint>(args, "-loginid") : null;

        AccountSettingsStore.LoadFromFile("account.config");

        ContentDownloader.InitializeSteam3(null, null);
        ContentDownloader.DownloadProgressChanged = OnDownloadProgressChanged;
        ContentDownloader.DownloadCompleted = OnDownloadDataCompleted;
    }

    // Update is called once per frame
    private void Update()
    {
    }

    private void OnGUI()
    {
        if (GUI.Button(new Rect(5, 5, 100, 25), "Download addon"))
        {
            DownloadDataAsync(2129643967);
        }
    }

    private static int IndexOfParam(string[] args, string param)
    {
        for (var x = 0; x < args.Length; ++x)
            if (args[x].Equals(param, StringComparison.OrdinalIgnoreCase))
                return x;
        return -1;
    }

    private static bool HasParameter(string[] args, string param)
    {
        return IndexOfParam(args, param) > -1;
    }

    private static T GetParameter<T>(string[] args, string param, T defaultValue = default)
    {
        var index = IndexOfParam(args, param);

        if (index == -1 || index == args.Length - 1)
            return defaultValue;

        var strParam = args[index + 1];

        var converter = TypeDescriptor.GetConverter(typeof(T));
        if (converter != null)
            return (T)converter.ConvertFromString(strParam);

        return default;
    }
}

This is the current line that is giving me troubles: https://github.com/uta-org/DepotDownloader/blob/uzsourcetoolkit/ContentDownloader.cs#L836

This is what the ReadFully method contains:

private static byte[] ReadFully(this Stream input)
        {
            using (var ms = new MemoryStream())
            {
                input.CopyTo(ms);
                return ms.ToArray();
            }
        }

And this is what happens:

...

After pressing F10, this is what it looks like. the highlight disappeared:

...

Other times it gets stuck here:

...

I suppose that the problem is that maybe the Task.Run from here is getting into a deadlock. Maybe because the resource that is trying to be read is busy? I don't exactly what to do at this point.

Can anybody guide me in order to resolve this problem?

z3nth10n
  • 2,341
  • 2
  • 25
  • 49
  • Well, as you can see the original code isn't designed to run synchronously. So, I can't confirm that this could be a possible answer. As you can see, the code is getting called on parallel using semaphores. Thanks! – z3nth10n Jun 19 '20 at 01:44
  • You are running it synchronously when you call `ContentDownloader.DownloadPubfileAsync(fromWhere).GetAwaiter().GetResult()`, that forces the code to run synchronously, and that can lead to deadlocks like the one you're experiencing. If you call it with the helper in the accepted answer of the post I have linked as duplicate the deadlock will not happen. – Gusman Jun 19 '20 at 01:50
  • Thanks! It solved my issue. Now I can see that an NRE is generating when the code tries to read the FileStream. – z3nth10n Jun 19 '20 at 02:15

0 Answers0