Skip to content

fix: prevent PdfiumLibraryBindingsAlreadyInitialized race condition#1255

Open
ethancls wants to merge 1 commit into
stumpapp:mainfrom
ethancls:fix/pdfium-concurrent-binding
Open

fix: prevent PdfiumLibraryBindingsAlreadyInitialized race condition#1255
ethancls wants to merge 1 commit into
stumpapp:mainfrom
ethancls:fix/pdfium-concurrent-binding

Conversation

@ethancls

Copy link
Copy Markdown

Problem

When multiple PDFs are processed concurrently (e.g. during library scanning), every call to PdfProcessor::renderer() attempts Pdfium::bind_to_library(), which can only succeed once per process. The second and subsequent concurrent calls fail with:

PdfiumLibraryBindingsAlreadyInitialized → 500 Internal Server Error

This breaks PDF thumbnail generation, page rendering, and the built-in reader for all PDF files when more than one PDF is scanned or opened at the same time.

Fix

Wrap the Pdfium instance in a global Mutex<Option<Pdfium>>:

Changes

core/src/filesystem/media/format/pdf.rs — 23 lines added, 16 removed. No other files touched.

Related

Tested

Built and deployed on macOS (ARM64 Docker) with a library containing 100+ PDFs — all thumbnails now generate correctly, no more 500 errors.

🤖 Generated with Claude Code

Wrap the Pdfium instance in a global `Mutex<Option<Pdfium>>` so that
`Pdfium::bind_to_library()` is only called once.  Concurrent PDF
processing (scanner, page prerendering, or rapid page requests) would
previously fail because every call to `renderer()` tried to bind the
native library, which succeeds at most once per process.

The `PdfiumRef` wrapper holds the lock guard and derefs to `Pdfium`,
so callers need no changes.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings June 20, 2026 19:54

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR addresses a concurrency failure in PDF processing by ensuring Pdfium::bind_to_library() is only performed once per process and by serializing PDFium usage behind a global mutex to avoid concurrent initialization and access issues.

Changes:

  • Introduces a global static PDFIUM: Mutex<Option<Pdfium>> to cache a single initialized Pdfium instance.
  • Adds a PdfiumRef wrapper around the mutex guard to provide ergonomic Deref<Target = Pdfium> access while keeping the lock held.
  • Updates PdfProcessor::renderer() to initialize on first use and reuse the cached instance thereafter.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +34 to +42
/// Held while PDFium is in use; derefs to `Pdfium` for ergonomic access.
pub struct PdfiumRef<'a>(MutexGuard<'a, Option<Pdfium>>);

impl<'a> Deref for PdfiumRef<'a> {
type Target = Pdfium;
fn deref(&self) -> &Self::Target {
self.0.as_ref().expect("PDFium not initialized")
}
}
Comment on lines +200 to +205
if let Some(path) = pdfium_path {
let bindings = Pdfium::bind_to_library(path).map_err(|e| {
tracing::error!(provided_path = ?path, ?e, "Failed to bind to PDFium library at provided path");
FileError::PdfConfigurationError
})?;
*guard = Some(Pdfium::new(bindings));
@aaronleopold

Copy link
Copy Markdown
Collaborator

There is already an active effort to improve this situation in #1209

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

Successfully merging this pull request may close these issues.

3 participants