Skip to content

Conversation

@ghost
Copy link

@ghost ghost commented Dec 15, 2025

Summary

  • Implements lazy fontconfig initialization in PixelRendererProcessor to prevent deadlock when using fork-based multiprocessing
  • Adds comprehensive tests for single fork, double fork, and spawn scenarios
  • Fixes deadlock issues with PyTorch DataLoader and TRL's pack_dataset()

Problem

When using PixelRendererProcessor with PyTorch's DataLoader (num_workers > 0) or TRL's pack_dataset(), processes would deadlock and hang indefinitely.

Root Cause:

  • Fontconfig uses internal mutexes to protect its data structures
  • When fork() creates a child process, it copies the mutex state but not the threads
  • If fontconfig was initialized in the parent process, child processes inherit broken mutex state
  • Child processes deadlock when trying to acquire mutexes owned by non-existent threads

Reproduction: Double fork scenario (most common in practice)

  1. Create PixelRendererProcessor in main process (fontconfig initialized)
  2. Call pack_dataset() which forks → First child inherits locked mutexes
  3. First child creates DataLoader with num_workers>0 → Second fork inherits locked mutexes
  4. Second child tries to render text → Deadlock when accessing fontconfig

Solution

Implement lazy initialization of fontconfig:

  • Parent process: Only stores configuration parameters, never initializes fontconfig
  • Child processes: Each child initializes fontconfig independently on first render_text() call
  • Fork detection: Tracks process ID to detect forks and re-initialize when needed

Changes

pixel_renderer/processor.py:

  • Store fontconfig parameters instead of initializing in __init__
  • Add _ensure_fontconfig_initialized() method called before rendering
  • Track initialization per-process using PID comparison
  • Convert fontconfig_path to property with lazy initialization

tests/pixel_renderer/test_no_deadlock.py:

  • test_no_deadlock_with_dataloader_single_fork: Basic single fork test
  • test_no_deadlock_with_dataloader_double_fork: Reproduces the issue scenario (main test)
  • test_no_deadlock_with_dataloader_spawn: Validates spawn still works (baseline)

Test Plan

  • Run new deadlock tests: pytest tests/pixel_renderer/test_no_deadlock.py -v
  • All 3 tests pass (single fork, double fork, spawn)
  • Run existing test suite to ensure no regressions
  • Test with real-world PyTorch DataLoader usage
  • Test with TRL's pack_dataset() function

References

Fixes #13

🤖 Generated with Claude Code

AmitMY and others added 2 commits December 15, 2025 20:01
Implements lazy fontconfig initialization to fix deadlock issues when
using PixelRendererProcessor in forked worker processes (e.g., PyTorch
DataLoader with fork multiprocessing).

The issue occurred because fontconfig's internal mutexes were initialized
in the parent process, then inherited by child processes during fork().
This caused child processes to deadlock when trying to acquire locks owned
by threads that don't exist in the child.

The fix ensures fontconfig is initialized independently in each process:
- Parent process stores configuration only, never initializes fontconfig
- Each child process initializes fontconfig on first render_text() call
- Detects forks via PID tracking and re-initializes if needed

Fixes #13

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Add python3-dev dependency to GitHub Actions setup
- Create apt cache directory before setting permissions
- Increase DataLoader test timeouts from 3-5s to 10s for more reliable testing

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
@AmitMY AmitMY merged commit 872a332 into main Dec 15, 2025
1 of 2 checks passed
@AmitMY AmitMY deleted the fix/fontconfig-fork-deadlock branch December 15, 2025 19:22
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.

FontConfig is not thread safe

1 participant