3

Context: Xcode 5, iOS 7.1.

I have some code that generates a PDF with the option of embedding an existing PDF within it, using PSPDFKit to render the pages of the existing PDF. 99% of the time, the code works fine; but in a reproducible 1% of the time, I get a crash (exc_bad_access). I can't explain what's different when I reproduce the crash- generally I need to make the app generate the PDF N times (where today N=5, other days N=2) and then the crash happens.

The code simply makes these two calls in a loop:

CGSize pageSize = CGSizeMake(612*3, 792*3);
{
    UIGraphicsBeginPDFPageWithInfo(CGRectMake(0, 0, size.width, size.height), nil);

    NSError *error = nil;

     [pdfDoc renderPage:innerPageNum
                    inContext:UIGraphicsGetCurrentContext();
                      withSize:size
          clippedToRect:CGRectZero
        withAnnotations:nil
                      options:nil
                         error:&error];
}

And occasionally it crashes in UIGraphicsBeginPDFPageWithInfo, always at the point below in the assembly code. Has anyone ever seen anything like this or have any clues to debug? Without access to the UIKit source, I'm pretty clueless.

CoreGraphics`CGPDFSecurityHandlerIsUnlocked:

0x41559ff:  pushl  %ebp
0x4155a00:  movl   %esp, %ebp
0x4155a02:  xorb   %al, %al
0x4155a04:  movl   0x8(%ebp), %ecx
0x4155a07:  testl  %ecx, %ecx
0x4155a09:  je     0x4155a12                 ; CGPDFSecurityHandlerIsUnlocked + 19
0x4155a0b:  cmpb   $0x0, 0x7c(%ecx)   <<< Thread 1: EXC_BAD_ACCESS (code=2, address=0xde)
0x4155a0f:  setne  %al
0x4155a12:  movzbl %al, %eax
0x4155a15:  popl   %ebp
0x4155a16:  ret  

which, if I could attach an image to show the stack trace I believe would show that that function was eventually reached 21 hidden stack levels deep from this call:

UIKit`UIGraphicsBeginPDFPageWithInfo:

0x431914f:  pushl  %ebp
0x4319150:  movl   %esp, %ebp
0x4319152:  pushl  %ebx
0x4319153:  pushl  %edi
0x4319154:  pushl  %esi
0x4319155:  subl   $0x5c, %esp
0x4319158:  calll  0x431915d                 ; UIGraphicsBeginPDFPageWithInfo + 14
0x431915d:  popl   %esi
0x431915e:  movl   $0x2, %ecx
0x4319163:  calll  0x4318cb7                 ; GetCurrentContext
0x4319168:  movl   %eax, %edi
0x431916a:  movl   $0x2, %ecx
0x431916f:  calll  0x4318ce1                 ; GetCurrentContextAuxInfo
0x4319174:  testl  %edi, %edi
0x4319176:  je     0x43192cb                 ; UIGraphicsBeginPDFPageWithInfo + 380
0x431917c:  testl  %eax, %eax
0x431917e:  je     0x43192cb                 ; UIGraphicsBeginPDFPageWithInfo + 380
0x4319184:  movl   $0x2, %ecx
0x4319189:  calll  0x4318ce1                 ; GetCurrentContextAuxInfo
0x431918e:  testl  %eax, %eax
0x4319190:  je     0x43192bd                 ; UIGraphicsBeginPDFPageWithInfo + 366
0x4319196:  cmpb   $0x0, 0x20(%eax)
0x431919a:  movl   %eax, %ebx
0x431919c:  je     0x43191a6                 ; UIGraphicsBeginPDFPageWithInfo + 87
0x431919e:  movl   %edi, (%esp)
0x43191a1:  calll  0x4aaa848                 ; symbol stub for: CGPDFContextEndPage
0x43191a6:  leal   0x8(%ebp), %eax          <<< Thread 1: EXC_BAD_ACCESS (code=2, address=0xde)
Marc
  • 81
  • 4
  • I'm getting the same crash on Mac OS X 10.10.1. – Aderstedt Jan 16 '15 at 14:23
  • 1
    Follow-up: this August (2015) Apple did finally reply to my radar report on this, saying that they believed this bug was fixed in a beta release of iOS 9. We had in the meantime implemented a workaround that sounds like your suggestion @Chadwick (though I'd have to revisit the particulars to be sure) - and to date we haven't actually gone back and retested the crash scenario without the workaround to see if iOS 9 actually resolves the issue. – Marc Nov 28 '15 at 21:12

2 Answers2

1

I'm not sure if this is the exact same thing, but I answered a similar sounding issue here: UIGraphicsBeginPDFPage() randomly crashes on 64bit devices (CGPDFSecurityManagerCreateDecryptor ())

The gist of the solution there was to delay calling CGPDFDocumentRelease for any PDFs utilized in the target PDF until after the target PDF is closed with UIGraphicsEndPDFContext. For me that meant unfortunately not releasing some memory until the end of the process even though I should be able to, but it does appear to work.

Community
  • 1
  • 1
Chadwick
  • 944
  • 12
  • 15
  • While this link may answer the question, it is better to include the essential parts of the answer here and provide the link for reference. Link-only answers can become invalid if the linked page changes. – Brian Oct 19 '15 at 18:56
  • 1
    Good call; I edited the answer to include the basic idea of the linked solution. – Chadwick Oct 19 '15 at 21:26
0

For me this occured when I was also trying to release it (aka the currentContext) with CGContextRelease after:

UIGraphicsEndPDFContext();
CGContextRelease(pdfContext);//<-comment this out to solve

Turns out I only needed UIGraphicsEndPDFContext();, and for some reason (which I can only assume involves async called) even calling CGContextRelease AFTER calling EndPDFContext, still caused EXC_BAD_ACCESS on the EndPDFContext line.

Albert Renshaw
  • 17,282
  • 18
  • 107
  • 195