Skip to content

Commit a32f018

Browse files
authored
PHPLIB-345: Fix PHP shutdown error with dangling writable streams (#779)
* PHPLIB-345: Fix PHP shutdown error with dangling writable streams * Apply feedback from code review * Extract HEREDOC code to variable to avoid phpcs issues
1 parent cdeff1d commit a32f018

File tree

2 files changed

+40
-0
lines changed

2 files changed

+40
-0
lines changed

src/GridFS/StreamWrapper.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,14 @@ class StreamWrapper
5757
/** @var ReadableStream|WritableStream|null */
5858
private $stream;
5959

60+
public function __destruct()
61+
{
62+
/* This destructor is a workaround for PHP trying to use the stream well
63+
* after all objects have been destructed. This can cause autoloading
64+
* issues and possibly segmentation faults during PHP shutdown. */
65+
$this->stream = null;
66+
}
67+
6068
/**
6169
* Return the stream's file document.
6270
*
@@ -88,6 +96,10 @@ public static function register($protocol = 'gridfs')
8896
*/
8997
public function stream_close()
9098
{
99+
if (! $this->stream) {
100+
return;
101+
}
102+
91103
$this->stream->close();
92104
}
93105

tests/GridFS/BucketFunctionalTest.php

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,17 +18,22 @@
1818
use function array_merge;
1919
use function call_user_func;
2020
use function current;
21+
use function exec;
2122
use function fclose;
2223
use function fread;
2324
use function fwrite;
2425
use function hash_init;
26+
use function implode;
2527
use function is_callable;
2628
use function min;
2729
use function sprintf;
2830
use function str_repeat;
2931
use function stream_get_contents;
3032
use function strlen;
33+
use function strncasecmp;
3134
use function substr;
35+
use const PHP_EOL;
36+
use const PHP_OS;
3237

3338
/**
3439
* Functional tests for the Bucket class.
@@ -708,6 +713,29 @@ public function testExistingIndexIsReused()
708713
$this->assertIndexNotExists($this->chunksCollection->getCollectionName(), 'files_id_1_n_1');
709714
}
710715

716+
public function testDanglingOpenWritableStream()
717+
{
718+
if (! strncasecmp(PHP_OS, 'WIN', 3)) {
719+
$this->markTestSkipped('Test does not apply to Windows');
720+
}
721+
722+
$path = __DIR__ . '/../../vendor/autoload.php';
723+
$command = <<<CMD
724+
php -r "require '$path'; \\\$stream = (new MongoDB\Client)->test->selectGridFSBucket()->openUploadStream('filename', ['disableMD5' => true]);" 2>&1
725+
CMD;
726+
727+
@exec(
728+
$command,
729+
$output,
730+
$return
731+
);
732+
733+
$this->assertSame(0, $return);
734+
$output = implode(PHP_EOL, $output);
735+
736+
$this->assertSame('', $output);
737+
}
738+
711739
/**
712740
* Asserts that a collection with the given name does not exist on the
713741
* server.

0 commit comments

Comments
 (0)