Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PrintToPDFCommand hangs forever when printing to PDF #37

Open
ststeiger opened this issue Mar 19, 2019 · 3 comments
Open

PrintToPDFCommand hangs forever when printing to PDF #37

ststeiger opened this issue Mar 19, 2019 · 3 comments

Comments

@ststeiger
Copy link

PrintToPDFCommand hangs forever when printing to PDF

public static double cm2inch(double centimeters)
{
    return centimeters * 0.393701;
}

PrintToPDFCommand printCommand = new PrintToPDFCommand()
{
    MarginTop = 0,
    MarginLeft = 0,
    MarginRight = 0,
    MarginBottom = 0,
    PrintBackground = true,
    Landscape = false,
    PaperWidth = cm2inch(21),
    PaperHeight = cm2inch(29.7)
};


System.Console.WriteLine("Printing PDF");
CommandResponse<PrintToPDFCommandResponse> pdf = await chromeSession.SendAsync(printCommand);
System.Console.WriteLine("PDF printed.");

byte[] pdfData = System.Convert.FromBase64String(pdf.Result.Data);
System.IO.File.WriteAllBytes("output.pdf", pdfData);
System.Console.WriteLine("PDF stored");
@ststeiger
Copy link
Author

ststeiger commented Apr 4, 2019

Found the bug:
If scale is not present, then it throws an error, but because it's in task.run, it's not reported.
==> the await never returns...
Setting Scale = x is mandatory.

scale is outside [0.1 - 2] range

bug here:

        private Task<ICommandResponse> SendCommand(Command command, CancellationToken cancellationToken)
        {
            var settings = new JsonSerializerSettings
            {
                ContractResolver = new MessageContractResolver(),
                NullValueHandling = NullValueHandling.Ignore,
            };
            var requestString = JsonConvert.SerializeObject(command, settings);
            var requestResetEvent = new ManualResetEventSlim(false);
            _requestWaitHandles.AddOrUpdate(command.Id, requestResetEvent, (id, r) => requestResetEvent);
            return Task2.Run(() =>
            {
                EnsureInit();
                _webSocket.Send(requestString);
                requestResetEvent.Wait(cancellationToken);
                ICommandResponse response = null;
                _responses.TryRemove(command.Id, out response);
                _requestWaitHandles.TryRemove(command.Id, out requestResetEvent);
                return response;
            });
        }

@ststeiger
Copy link
Author

OK, found the bug.
In MasterDev.ChromeDevTools\ChromeSession.cs
you do
task.ContinueWith( t => tcs.SetResult((TDerived)t.Result))
However, if it returns an error, (TDerived)t.Result yields an exception, and the await never returns.
It looks like you need to catch the errors there:

        private Task<TDerived> CastTaskResult<TBase, TDerived>(Task<TBase> task) where TDerived: TBase
        {
            var tcs = new TaskCompletionSource<TDerived>();
            task.ContinueWith(
                // t => tcs.SetResult((TDerived)t.Result)
                delegate (Task<TBase> t) {
                    try
                    {
                        TDerived res = (TDerived)t.Result;
                        tcs.SetResult(res);
                    }
                    catch (System.Exception ex)
                    {
                        tcs.SetException(ex);
                    }
                }, TaskContinuationOptions.OnlyOnRanToCompletion
            );

            task.ContinueWith(
                    // t => tcs.SetException(t.Exception.InnerExceptions)
                    delegate (Task<TBase> t) {
                        try
                        {
                            tcs.SetException(t.Exception.InnerExceptions);
                        }
                        catch (System.Exception ex)
                        {
                            tcs.SetException(ex);
                        }


                    }
                    ,TaskContinuationOptions.OnlyOnFaulted
            );

            task.ContinueWith(
                    // t => tcs.SetCanceled()
                    delegate (Task<TBase> t)
                    {
                        try
                        {
                            tcs.SetCanceled();
                        }
                        catch (System.Exception ex)
                        {
                            tcs.SetException(ex);
                        }
                    }
                , TaskContinuationOptions.OnlyOnCanceled
            );

            return tcs.Task;
        }

@ststeiger
Copy link
Author

And it might be better to output the actual error:

private Task<TDerived> CastTaskResult<TBase, TDerived>(Task<TBase> task) where TDerived: TBase
{
    TaskCompletionSource<TDerived> tcs = new TaskCompletionSource<TDerived>();
    task.ContinueWith(
        // t => tcs.SetResult((TDerived)t.Result)
        delegate (Task<TBase> t) 
        {
            try
            {
                TDerived res = (TDerived)t.Result;
                tcs.SetResult(res);
            }
            catch (System.Exception ex)
            {
                ErrorResponse error = t.Result as ErrorResponse;

                if (error != null)
                {
                    string errorMessage = "";

                    try
                    {
                        errorMessage += "Id " + System.Convert.ToString(error.Id, System.Globalization.CultureInfo.InvariantCulture) + System.Environment.NewLine;
                    }
                    catch
                    { }


                    try
                    {
                        errorMessage += "Error " + System.Convert.ToString(error.Error.Code, System.Globalization.CultureInfo.InvariantCulture) + System.Environment.NewLine;
                    }
                    catch
                    { }


                    try
                    {
                        errorMessage += error.Error.Message + System.Environment.NewLine;
                    }
                    catch
                    { }


                    try
                    {
                        errorMessage += error.Method;
                    }
                    catch
                    { }


                    tcs.SetException( new Exception(errorMessage, ex) );
                }
                else
                    tcs.SetException(ex);
            }
        }, TaskContinuationOptions.OnlyOnRanToCompletion
    );

    task.ContinueWith(
            // t => tcs.SetException(t.Exception.InnerExceptions)
            delegate (Task<TBase> t) 
            {
                try
                {
                    tcs.SetException(t.Exception.InnerExceptions);
                }
                catch (System.Exception ex)
                {
                    tcs.SetException(ex);
                }


            }
            ,TaskContinuationOptions.OnlyOnFaulted
    );

    task.ContinueWith(
            // t => tcs.SetCanceled()
            delegate (Task<TBase> t)
            {
                try
                {
                    tcs.SetCanceled();
                }
                catch (System.Exception ex)
                {
                    tcs.SetException(ex);
                }
            }
        , TaskContinuationOptions.OnlyOnCanceled
    );

    return tcs.Task;
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant