xamarin/xamarin-macios

The application crashes while using DrawPDFPage for specific document in DidEnterBackground method.

Closed this issue · 8 comments

Apple platform

iOS

Framework version

Other

Affected platform version

VS for Mac 2019 v8.10.25, Xamarin.iOS v16.4.0.23

Description

I’m currently using CGPDFPage and CGContext to convert a PDF into an image. The process works fine in most cases, but I’ve encountered an issue when the PDF file is larger than 50 MB and the application is sent to the background by pressing the home button and then reopened. This problem only occurs on physical devices; emulators work without any issues.

We are using the following code for this conversion:

fileStream.CopyTo(memoryStream);
CGDataProvider provider = new CGDataProvider(memoryStream.ToArray());
CGPDFDocument cGPDFDocument = null;
 image = null;
    cGPDFDocument = new CGPDFDocument(provider);
using(CGPDFPage pdfPage = cGPDFDocument?.GetPage(1))
{
     if (pdfPage != null)
    {
        CGRect rect = pdfPage.GetBoxRect(CGPDFBox.Media);
        if (pdfPage.RotationAngle == 90 || pdfPage.RotationAngle == 270)
        {
            rect = new CGRect(rect.X, rect.Y, rect.Height, rect.Width);
        }
        nfloat factor = (nfloat)0.5;
        CGRect bounds = new CGRect(rect.X * factor, rect.Y * factor, rect.Width * factor, rect.Height * factor);
        UIGraphics.BeginImageContext(bounds.Size);
        CGContext context = UIGraphics.GetCurrentContext();
        context.SetFillColor(1.0f, 1.0f, 1.0f, 1.0f);
        context.FillRect(bounds);
        context.TranslateCTM(0, bounds.Height);
        context.ScaleCTM(factor, -factor);
        context.ConcatCTM(pdfPage.GetDrawingTransform(CGPDFBox.Crop, rect, 0, true));
        context.SetRenderingIntent(CGColorRenderingIntent.Default);
        context.InterpolationQuality = CGInterpolationQuality.Default;
        context.DrawPDFPage(pdfPage);
        image = UIGraphics.GetImageFromCurrentImageContext();
        UIGraphics.EndImageContext();
        imageView.Image = image; 
        parentView.AddSubview(imageView);
    }
}

We’ve created a simple Xamarin.iOS application to replicate this issue, with the problematic PDF included in the Assets. You can download the sample here: https://www.syncfusion.com/downloads/support/directtrac/general/ze/PdfToImageSample-556012354

We’ve also recorded the issue for reference, which you can view here: https://www.syncfusion.com/downloads/support/directtrac/general/ze/CrashBGImgRec-1376481150

The issue consistently occurs in the line context.DrawPDFPage(pdfPage); in my application. In the provided sample, the issue happens consistently when a breakpoint is placed on that line, and it can also occur randomly without a breakpoint.

This function is being invoked in the DidEnterBackground override method of AppDelegate.

Do we need to set any specific configurations to properly retrieve the image from CGPDFPage and add it to the context?

Steps to Reproduce

  1. Open the application at the following link: https://www.syncfusion.com/downloads/support/directtrac/general/ze/PdfToImageSample-556012354
  2. Build and run the application on the physical device.
  3. make the application to enter the background by pressing the home button
  4. Open the application again.
  5. Application crashes at "context.DrawPDFPage(pdfPage);"

Did you find any workaround?

No, not yet

Relevant logs

No response

The pdf renders on my iPad Pro 3, which device are you trying on? It might be a memory issue, where the app ends up consuming too much memory and is killed.

Can you see if there are any crash reports (https://github.com/xamarin/xamarin-macios/wiki/Diagnosis#crash-reports) or if anything is printed to the device log (https://support.apple.com/en-in/guide/console/cnsl1012/mac)?

Hi @rolfbjarne
I tested the code on the iPad (5th gen) with iPadOS 16.7.8 and iPad Pro (11 inches) with iPadOS 17.6.1 and faced the same issue. Could you please try debugging the code where you can consistently replicate the issue? This issue is consistently replicated in our project and rarely in the provided solution.
Log message:
image
Device Logs
GettingStartediOS-ErrorLog.zip

GettingStartediOS-ErrorLog.zip

That's because you triggered a watchdog, something took too long:

exhausted real (wall clock) time allowance of 10.00 seconds

From the stack trace it looks like the main thread is waiting on a lock, but unfortunately the important symbols have been stripped away, so there's just memory addresses.

This can be improved by adding the following to your csproj, which will disable native symbol stripping, and thus provide better stack traces in crash reports:

<PropertyGroup>
    <NoSymbolStrip>true</NoSymbolStrip>
</PropertyGroup>

I tested the code on the iPad (5th gen) with iPadOS 16.7.8 and iPad Pro (11 inches) with iPadOS 17.6.1 and faced the same issue. Could you please try debugging the code where you can consistently replicate the issue? This issue is consistently replicated in our project and rarely in the provided solution.

Your project is a Xamarin.iOS project, and support for Xamarin.iOS ended earlier this year.

I previously tested your project real quick to see if anything was obviously wrong somewhere, but I didn't find anything. A more involved support is out of scope for a product that's been discontinued already.

If you upgrade your project to .NET, we'll be more than happy to investigate deeper any issues you run into (the problem you're running into might not even happen anymore).

Hi @rolfbjarne
I have added NoSymbolStrip true and got the following details
GettingStartediOS-2024-09-18-201323.zip
image
image
image
image

If this is a memory issue that happens on physical devices only how can we handle this memory pile up issue only with certain PDF documents?

From the crash report:

exhausted real (wall clock) time allowance of 10.00 seconds

iOS terminated your app because it was stuck doing something for too long.

From the stack trace it looks like it took too long to render the pdf.

Maybe it would be possible to render it to an image on a background thread, and then just render the image on the main thread?

Hi @manojSF3414. We have added the "need-info" label to this issue, which indicates that we have an open question for you before we can take further action. This issue will be closed automatically in 7 days if we do not hear back from you by then - please feel free to re-open it if you come back to this issue after that time.

Hi @manojSF3414. Due to inactivity, we will be closing this issue. Please feel free to re-open this issue if the issue persists. For enhanced visibility, if over 7 days have passed, please open a new issue and link this issue there. Thank you.