From 3eb7785aa43d97c27bd287cbac9d9a82b321f63a Mon Sep 17 00:00:00 2001 From: Michael Wegener Date: Tue, 21 Jul 2026 12:21:38 +0200 Subject: [PATCH] fix(build): phpize-clean default + stale .so removal (SIGSEGV fix) The /ext directory is a shared bind mount across all 12 Docker containers (PHP 8.2-8.5 x FB 3/4/5). If a container compiled against FB 5.0 headers (FB_API_VER=50) and a subsequent container with FB 3.0 loads the stale .so, IResultSet::close() dispatches through a vtable slot that doesn't exist in FB 3.0's libfbclient -> NULL function pointer -> SIGSEGV during shutdown. Root cause: Stale .so compiled against FB 5.0 headers, loaded with FB 3.0 client. The #if FB_API_VER >= 40 guard in closeCursor() (fb_statement.hpp:409) works correctly when the .so matches the runtime library - the bug only manifests on header/library version mismatch. Changes: - build-extension action: default phpize-clean 'false' -> 'true' - build-extension action: rm -f stale .so files before phpize --clean - ci.yml: add stale .so removal + phpize --clean to pdo_fbird standalone build - .gitignore: add /debian/ and /dist/ build output directories Validated: 12/12 containers pass (4,321 tests, 0 failures) after building in FB5 container first (worst-case stale-.so scenario). Fixes: PHP 8.5/FB3 SIGSEGV during CI (was incorrectly attributed to PHP 8.5 compatibility - it was a stale build artifact issue) --- .github/actions/build-extension/action.yml | 13 +++++++++++-- .github/workflows/ci.yml | 3 +++ .gitignore | 7 +++++++ 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/.github/actions/build-extension/action.yml b/.github/actions/build-extension/action.yml index d777ad23..f93e8632 100644 --- a/.github/actions/build-extension/action.yml +++ b/.github/actions/build-extension/action.yml @@ -38,9 +38,9 @@ inputs: required: false default: '' phpize-clean: - description: 'Run phpize --clean before phpize' + description: 'Run phpize --clean and remove stale .so files before phpize. Prevents header/library version mismatches when the source tree is shared between containers with different Firebird client versions (e.g. FB 3.0 vs FB 5.0).' required: false - default: 'false' + default: 'true' php-bin-dir: description: 'Directory containing php/php-config binaries (prepended to PATH)' required: false @@ -67,6 +67,15 @@ runs: export PATH="$PHP_BIN_DIR:$PATH" fi if [ "$PHPIZE_CLEAN" = 'true' ]; then + # Remove stale .so files BEFORE phpize --clean. + # jane: The /ext directory is a shared bind mount across all Docker + # containers (PHP 8.2-8.5 × FB 3/4/5). If a previous container compiled + # against FB 5.0 headers (FB_API_VER=50) and the current container has + # FB 3.0 (FB_API_VER=30), the stale .so calls IResultSet::close() which + # dispatches through a vtable slot that doesn't exist in FB 3.0's + # libfbclient → NULL function pointer → SIGSEGV during shutdown. + # See: src/cpp/fb_statement.hpp:409 (#if FB_API_VER >= 40 guard). + rm -f modules/firebird.so pdo_fbird/modules/pdo_fbird.so 2>/dev/null || true phpize --clean fi phpize diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 463e556a..bc7f99d3 100755 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -175,6 +175,9 @@ jobs: run: | set -eu cd pdo_fbird + # Remove stale .so before phpize (same rationale as build-extension action) + rm -f modules/pdo_fbird.so 2>/dev/null || true + phpize --clean phpize ./configure --with-pdo-fbird --with-firebird=/opt/firebird-client make -j"$(nproc)" diff --git a/.gitignore b/.gitignore index ee8e8b10..fc5b8cc7 100755 --- a/.gitignore +++ b/.gitignore @@ -173,3 +173,10 @@ pdo_fbird_driver.c pdo_fbird_stmt.c pdo_fbird_error.c .opencode/ + +# Debian package build output (generated by packaging/debian/build.sh) +# Source lives in packaging/debian/, not /debian/ +/debian/ + +# Distribution build output +/dist/