Skip to content

[Bug]: [macOS] PHP-FPM workers crash with SIGSEGV in gettext() → libintl → CFPreferences (fork-unsafe macOS API) #1656

@JacobDelcroix

Description

@JacobDelcroix

Platform

macOS

Operating system version

macOS Tahoe 26.3 (25D125)

System architecture

ARM64 (M1, M2, etc)

Herd Version

1.26.1

PHP Version

No response

Bug description

Description

PHP-FPM worker processes crash with a segmentation fault (signal 11) on specific pages when using Herd. The same pages load correctly with php artisan
serve. The issue affects all PHP versions (tested on 8.2, 8.3, 8.4, 8.5) and is not project-specific (reproduced across multiple Laravel projects
including Filament-based ones).

No PHP-FPM log entries are generated — the crash is silent from Herd's perspective, but macOS generates a crash report in
~/Library/Logs/DiagnosticReports/php83-fpm-*.ips.


Environment

  • Platform: macOS 26.3 Tahoe (Apple Silicon / ARM64)
  • Herd Version: latest
  • PHP Versions affected: 8.2, 8.3, 8.4, 8.5

Symptoms

  • 502 Bad Gateway on certain pages (not all)
  • php artisan serve works fine for the same pages
  • Nginx error log shows: upstream prematurely closed connection while reading response header from upstream
  • php-fpm.log is empty — no errors logged
  • macOS crash report generated: ~/Library/Logs/DiagnosticReports/php83-fpm-*.ips

Root Cause

The crash report reveals a SIGSEGV in PHP-FPM worker processes caused by gettext() calling macOS CoreFoundation APIs that are not fork-safe:

gettext()
→ libintl_dcigettext
→ _libintl_locale_name_default
→ CFPreferencesCopyAppValueWithContainerAndConfiguration ← macOS CoreFoundation
→ -[_CFXPreferences withSearchListForIdentifier:...]
→ dispatch_apply (GCD, multi-threaded)
→ SIGSEGV (EXC_BAD_ACCESS / KERN_INVALID_ADDRESS)

The crash note in the .ips file confirms the fork context:
"asi": {
"CoreFoundation": ["*** multi-threaded process forked ***"],
"libsystem_c.dylib": ["crashed on child side of fork pre-exec"]
}

When libintl needs to determine the system locale at runtime, it calls CFPreferences via Grand Central Dispatch (GCD). GCD dispatch queues inherited from
the PHP-FPM master process are in an invalid state in forked child workers, leading to the crash. php artisan serve is unaffected because it uses the CLI
SAPI and does not fork.


Workaround

Adding locale environment variables to each PHP-FPM pool configuration file prevents libintl from querying CFPreferences at runtime, since the locale is
already defined in the environment:

File: ~/Library/Application Support/Herd/config/fpm/{version}-fpm.conf
(repeat for all installed versions: 8.2, 8.3, 8.4, 8.5)

env[LANG] = en_US.UTF-8
env[LC_ALL] = en_US.UTF-8

Then restart PHP services in Herd. The 502 errors stop immediately.


Suggested Fix

Herd should include LANG and LC_ALL environment variable defaults in the generated FPM pool configuration files, or pass them when spawning PHP-FPM worker
processes. This would prevent the fork-unsafe CFPreferences call that crashes the workers on macOS.


Note: This was diagnosed by inspecting crash reports in ~/Library/Logs/DiagnosticReports/ — the fact that php-fpm.log remains empty makes this very hard
to debug without knowing where to look. Better crash logging or a diagnostic tool in Herd would help surface this kind of issue.

Steps to reproduce

No response

Relevant log output

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions