From ad8e1879d9966bfe70d4ffa743f682a5d85a1689 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Tamarelle?= Date: Thu, 23 Nov 2023 16:02:30 +0100 Subject: [PATCH] PHPLIB-1313 Ensure the GridFS stream is saved when the script ends (#1197) --- CHANGELOG.md | 2 +- src/GridFS/StreamWrapper.php | 9 +++++---- tests/GridFS/BucketFunctionalTest.php | 29 +++++++++++++++++++-------- 3 files changed, 27 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5dc7290c5..9cdc381ea 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,4 +4,4 @@ ## 1.18.0 (unreleased) * Add `addSubscriber` and `removeSubscriber` methods to the `Client` class to ease dependency injection configuration - + * Fix GridFS stream closing when the PHP script ends diff --git a/src/GridFS/StreamWrapper.php b/src/GridFS/StreamWrapper.php index 71a36d07b..c9758cf9a 100644 --- a/src/GridFS/StreamWrapper.php +++ b/src/GridFS/StreamWrapper.php @@ -53,10 +53,11 @@ class StreamWrapper public function __destruct() { - /* This destructor is a workaround for PHP trying to use the stream well - * after all objects have been destructed. This can cause autoloading - * issues and possibly segmentation faults during PHP shutdown. */ - $this->stream = null; + /* Ensure the stream is closed so the last chunk is written. This is + * necessary because PHP would close the stream after all objects have + * been destructed. This can cause autoloading issues and possibly + * segmentation faults during PHP shutdown. */ + $this->stream_close(); } /** diff --git a/tests/GridFS/BucketFunctionalTest.php b/tests/GridFS/BucketFunctionalTest.php index c87003e24..6cf38c729 100644 --- a/tests/GridFS/BucketFunctionalTest.php +++ b/tests/GridFS/BucketFunctionalTest.php @@ -23,6 +23,7 @@ use function array_merge; use function call_user_func; use function current; +use function escapeshellarg; use function exec; use function fclose; use function fopen; @@ -39,7 +40,7 @@ use function strncasecmp; use function substr; -use const PHP_EOL; +use const PHP_BINARY; use const PHP_OS; /** @@ -853,21 +854,33 @@ public function testDanglingOpenWritableStream(): void $this->markTestSkipped('Test does not apply to Windows'); } - $path = __DIR__ . '/../../vendor/autoload.php'; - $command = <<test->selectGridFSBucket()->openUploadStream('filename', ['disableMD5' => true]);" 2>&1 -CMD; + $code = <<<'PHP' + require '%s'; + $client = new \MongoDB\Client(getenv('MONGODB_URI') ?: 'mongodb://127.0.0.1:27017/?serverSelectionTimeoutMS=100'); + $database = $client->selectDatabase(getenv('MONGODB_DATABASE') ?: 'phplib_test'); + $gridfs = $database->selectGridFSBucket(); + $stream = $gridfs->openUploadStream('hello.txt', ['disableMD5' => true]); + fwrite($stream, 'Hello MongoDB!'); + PHP; @exec( - $command, + implode(' ', [ + PHP_BINARY, + '-r', + escapeshellarg(sprintf($code, __DIR__ . '/../../vendor/autoload.php')), + '2>&1', + ]), $output, $return, ); + $this->assertSame([], $output); $this->assertSame(0, $return); - $output = implode(PHP_EOL, $output); - $this->assertSame('', $output); + $fileDocument = $this->filesCollection->findOne(['filename' => 'hello.txt']); + + $this->assertNotNull($fileDocument); + $this->assertSame(14, $fileDocument->length); } /**