refactored memfd handling to use FFI for Linux, added qdb_close_fd function
Some checks failed
PHPUnit / test (push) Has been cancelled

This commit is contained in:
2026-06-12 22:14:51 +02:00
parent b4d4de72f4
commit 560ca69ae8

View File

@ -99,24 +99,53 @@ function qdb_read_materialize_decrypted_db(): array {
return [$pdo, $fallback, -1]; return [$pdo, $fallback, -1];
} }
/**
* @return FFI|null libc handle with memfd_create + close (Linux only)
*/
function qdb_linux_libc_ffi() {
static $ffi = null;
if ($ffi !== null) {
return $ffi;
}
if (PHP_OS_FAMILY !== 'Linux' || !extension_loaded('ffi')) {
return null;
}
try {
$ffi = FFI::cdef(
'int memfd_create(const char *name, unsigned int flags);
int close(int fd);',
'libc.so.6'
);
} catch (Throwable $e) {
error_log('qdb_linux_libc_ffi: ' . $e->getMessage());
return null;
}
return $ffi;
}
function qdb_close_fd(int $fd): void {
if ($fd < 0) {
return;
}
if (function_exists('posix_close')) {
@posix_close($fd);
return;
}
$ffi = qdb_linux_libc_ffi();
if ($ffi !== null) {
$ffi->close($fd);
}
}
/** /**
* @return array{0: int, 1: string}|null [fd, /proc/self/fd/N] * @return array{0: int, 1: string}|null [fd, /proc/self/fd/N]
*/ */
function qdb_memfd_write(string $bytes): ?array { function qdb_memfd_write(string $bytes): ?array {
if (PHP_OS_FAMILY !== 'Linux') { $ffi = qdb_linux_libc_ffi();
if ($ffi === null) {
return null; return null;
} }
if (!extension_loaded('ffi')) {
return null;
}
static $ffi = null;
try { try {
if ($ffi === null) {
$ffi = FFI::cdef(
'int memfd_create(const char *name, unsigned int flags);',
'libc.so.6'
);
}
$MFD_CLOEXEC = 1; $MFD_CLOEXEC = 1;
$fd = (int)$ffi->memfd_create('qdb_read', $MFD_CLOEXEC); $fd = (int)$ffi->memfd_create('qdb_read', $MFD_CLOEXEC);
if ($fd < 0) { if ($fd < 0) {
@ -124,7 +153,7 @@ function qdb_memfd_write(string $bytes): ?array {
} }
$written = @file_put_contents('/proc/self/fd/' . $fd, $bytes); $written = @file_put_contents('/proc/self/fd/' . $fd, $bytes);
if ($written === false || $written !== strlen($bytes)) { if ($written === false || $written !== strlen($bytes)) {
@close($fd); qdb_close_fd($fd);
return null; return null;
} }
return [$fd, '/proc/self/fd/' . $fd]; return [$fd, '/proc/self/fd/' . $fd];
@ -204,7 +233,7 @@ function qdb_read_cache_reset(): void {
$state['signature'] = ''; $state['signature'] = '';
$state['pdo'] = null; $state['pdo'] = null;
if ($state['memfdFd'] >= 0) { if ($state['memfdFd'] >= 0) {
@close($state['memfdFd']); qdb_close_fd($state['memfdFd']);
} }
$state['memfdFd'] = -1; $state['memfdFd'] = -1;
if ($state['memfdPath'] !== '' && is_file($state['memfdPath'])) { if ($state['memfdPath'] !== '' && is_file($state['memfdPath'])) {