Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ All notable changes to `php-vips` will be documented in this file.

- better ffi startup diagnostics [ping-localhost]
- add setBlock() and setBlockUntrusted() to control operation blocking [jcupitt]
- fix startup with the default `ffi.enable=preload` [wadakatu]
- include the FFI error in the startup exception [wadakatu]

## 2.6.1 - 2025-12-10

Expand Down
2 changes: 1 addition & 1 deletion phpunit.xml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
stopOnFailure="false">
<testsuites>
<testsuite name="Vips Test Suite">
<directory suffix=".php">./tests/</directory>
<directory suffix="Test.php">./tests/</directory>
</testsuite>
</testsuites>
</phpunit>
19 changes: 13 additions & 6 deletions src/FFI.php
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,13 @@ class FFI
private static int $library_minor;
private static int $library_micro;

/**
* The last exception that FFI extension throws after loading library.
*
* @internal
*/
private static ?\FFI\Exception $ffi_last_exception = null;

public static function glib(): \FFI
{
self::init();
Expand Down Expand Up @@ -254,6 +261,7 @@ private static function libraryLoad(
string $interface
): ?\FFI {
Utils::debugLog("trying to open", ["libraryName" => $libraryName]);
self::$ffi_last_exception = null;
foreach (self::$libraryPaths as $path) {
Utils::debugLog("trying path", ["path" => $path]);
try {
Expand All @@ -265,6 +273,7 @@ private static function libraryLoad(
"msg" => "library load failed",
"exception" => $e->getMessage()
]);
self::$ffi_last_exception = $e;
}
}
return null;
Expand All @@ -281,11 +290,6 @@ private static function init(): void
if (!extension_loaded("ffi")) {
throw new Exception("FFI extension not loaded");
}
$enable = ini_get("ffi.enable");
if ($enable != "true" &&
$enable != "1") {
throw new Exception("ffi.enable set to '$enable', not 'true'");
}

$vips_libname = self::libraryName("libvips", 42);
$glib_libname = self::libraryName("libglib-2.0", 0);
Expand Down Expand Up @@ -317,7 +321,10 @@ private static function init(): void
}
$msg .= ". Make sure that you've installed libvips and that '$vips_libname'";
$msg .= " is on your system's library search path.";
throw new Exception($msg);
if (self::$ffi_last_exception instanceof \FFI\Exception) {
$msg .= " FFI extension error: ". self::$ffi_last_exception->getMessage();
}
throw new Exception($msg, 0, self::$ffi_last_exception);
}

$result = $vips->vips_init("");
Expand Down
54 changes: 54 additions & 0 deletions tests/StartupTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<?php

namespace Jcupitt\Vips\Test;

use Jcupitt\Vips;
use PHPUnit\Framework\TestCase;

/*
* ffi.enable is INI_SYSTEM, so it cannot be changed with ini_set(). These
* tests start a second PHP process with -d ffi.enable=... and check what
* php-vips does on startup.
*/
class StartupTest extends TestCase
{
public function testStartsWithDefaultFfiEnable()
{
[$output, $result_code] = $this->execFFI("ffi.enable=preload");

$this->assertEquals(0, $result_code);
$this->assertEquals(preg_match("/\d+\.\d+\.\d+/", implode("\n", $output)), 1);
}

public function testReportsFfiReasonWhenFfiDisabled()
{
[$output, $result_code] = $this->execFFI("ffi.enable=0");

$this->assertNotEquals(0, $result_code);
$this->assertTrue(strpos(implode("\n", $output), "FFI API is restricted") !== false);
}

private function execFFI(string $ffi_enable_arg): array
{
exec(
escapeshellarg(PHP_BINARY)
." -d "
.$ffi_enable_arg . " "
.escapeshellarg(__DIR__ . "/scripts/print-version.php")
." 2>&1",
$output,
$result_code
);

return [$output, $result_code];
}
}

/*
* Local variables:
* tab-width: 4
* c-basic-offset: 4
* End:
* vim600: expandtab sw=4 ts=4 fdm=marker
* vim<600: expandtab sw=4 ts=4
*/
11 changes: 11 additions & 0 deletions tests/scripts/print-version.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?php

/*
* Boots php-vips and prints the libvips version. Run by StartupTest in a
* separate PHP process so that ffi.enable, which is INI_SYSTEM, can be set
* per test.
*/

require __DIR__ . '/../../vendor/autoload.php';

echo Jcupitt\Vips\Config::version(), "\n";
Loading