From 8cb12c38b3c29f2d772190b2b399ab9482928a2d Mon Sep 17 00:00:00 2001 From: Erik van Velzen Date: Thu, 21 Jul 2022 00:02:38 +0200 Subject: [PATCH] add dlerror() information (#32) When the uplink library cannot be loaded, there is currently a generic message originating from PHP. This is in all PHP versions. This change adds extra information which will help the user diagnose the issue. Example of old output: Fatal error: Uncaught FFI\Exception: Failed loading '/app/build/libuplink-x86_64-linux.so' in /app/src/Uplink.php:42 Example of new output: Fatal error: Uncaught FFI\Exception: Failed loading '/app/build/libuplink-x86_64-linux.so'. /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.32' not found (required by /app/build/libuplink-x86_64-linux.so) in /app/src/Uplink.php:60 Fixes https://github.com/storj-thirdparty/uplink-php/issues/21 --- Jenkinsfile | 2 +- phpstan.neon | 8 -------- src/Uplink.php | 43 +++++++++++++++++++++++++++++++++++++++---- 3 files changed, 40 insertions(+), 13 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index c325df3..3984c98 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -147,7 +147,7 @@ pipeline { stage('PHPStan') { agent { docker { - image 'ghcr.io/phpstan/phpstan:1.0.2' + image 'ghcr.io/phpstan/phpstan:1.8.1' args '--mount type=volume,source=phpstan-cache,destination=/tmp/phpstan ' + '--user root:root ' + "--entrypoint='' " diff --git a/phpstan.neon b/phpstan.neon index 85b63ab..040a308 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -6,14 +6,6 @@ parameters: ignoreErrors: - '/Call to an undefined method FFI::.*/' - '/Access to an undefined property FFI\\CData::.*/' - - - message: '/Binary operation "-" between numeric-string and string results in an error./' - paths: - - test/ListObjectsTest.php - - - message: "#^Binary operation \"\\-\" between int and string results in an error\\.$#" - count: 1 - path: test/StatObjectTest.php - message: "#^Property Storj\\\\Uplink\\\\Access\\:\\:\\$scope is never read, only written\\.$#" count: 1 diff --git a/src/Uplink.php b/src/Uplink.php index 0d04985..4faec23 100644 --- a/src/Uplink.php +++ b/src/Uplink.php @@ -36,10 +36,45 @@ public static function create(): self $os = str_replace(' ', '_', strtolower(php_uname('s'))); $extension = strpos($os, 'windows') !== false ? 'dll' : 'so'; - $ffi = FFI::cdef( - file_get_contents($root . '/build/uplink-php.h'), - "{$root}/build/libuplink-{$arch}-{$os}.{$extension}" - ); + $libuplinkSo = "{$root}/build/libuplink-{$arch}-{$os}.{$extension}"; + try { + $ffi = FFI::cdef( + file_get_contents($root . '/build/uplink-php.h'), + $libuplinkSo + ); + } catch (\FFI\Exception $ffiException) { + // dlerror() may have a more detailed error. + // Example: no permission, wrong glibc version, unknown binary format etc. + // This check should really be in PHP core. + try { + $ffi2 = FFI::cdef(" + void *dlopen(const char *filename, int flags); + char *dlerror(); + int dlclose(void *handle); + "); + $handle = $ffi2->dlopen($libuplinkSo, 1); + $scope = Scope::exit(function() use ($handle, $ffi2) { + if ($handle !== null) { + $ffi2->dlclose($handle); + } + }); + $cError = $ffi2->dlerror(); + } catch (\Throwable $innerException) { + // error when calling dlopen/dlerror, rethrow original error + throw $ffiException; + } + + if ($cError == null) { + // dlerror had no info, rethrow original error + throw $ffiException; + } + + $dlErrorMessage = FFI::string($cError); + + throw new \FFI\Exception( + $ffiException->getMessage() . ": " . $dlErrorMessage + ); + } return new self($ffi); }