summaryrefslogtreecommitdiff
blob: 01eb2a6154b07798e6dc80665377c1a640eeafc8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
From c9430b844fbcedc9119e3d464f5f0c85feb7b197 Mon Sep 17 00:00:00 2001
From: Jerome Flesch <jflesch@openpaper.work>
Date: Sun, 4 Feb 2024 20:33:27 +0100
Subject: [PATCH] Backend/docexport PDF: Workaround Cairo bug that causes
 occasional crashes when exporting to generated PDF.

Closes #942
---
 .../src/paperwork_backend/docexport/pdf.py          | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/paperwork-backend/src/paperwork_backend/docexport/pdf.py b/paperwork-backend/src/paperwork_backend/docexport/pdf.py
index 160e60710..befded73c 100644
--- a/paperwork-backend/src/paperwork_backend/docexport/pdf.py
+++ b/paperwork-backend/src/paperwork_backend/docexport/pdf.py
@@ -115,6 +115,8 @@ class PdfCreator(object):
         )
         self.pdf_context = cairo.Context(self.pdf_surface)
 
+        self.gc_protection = []  # WORKAROUND(Jflesch): Cairo crash
+
     def set_page_size(self, img_size):
         # portrait or landscape
         if (img_size[0] < img_size[1]):
@@ -187,6 +189,16 @@ class PdfCreator(object):
             "pillow_to_surface", img,
             intermediate="jpeg", quality=int(self.quality * 100)
         )
+        # WORKAROUND(Jflesch):
+        # If Cairo supports JPEG embedding, we use
+        # cairo.ImageSurface.set_mime_data() instead of the usual Cairo
+        # surface functions to draw the image. It seems this function does
+        # not increment the ref counter of the surface object
+        # --> the Python GC tends to collect it while Cairo is still going
+        # to use it to generate the PDF.
+        # --> we have to keep a reference on it ourselves, until the page has
+        # been generated.
+        self.gc_protection.append(img_surface)
 
         self.pdf_context.save()
         try:
@@ -199,6 +211,7 @@ class PdfCreator(object):
 
     def next_page(self):
         self.pdf_context.show_page()
+        self.gc_protection = []  # WORKAROUND(Jflesch): Cairo crash
 
     def finish(self):
         self.pdf_surface.flush()
-- 
GitLab