Exception thrown in synchronous call "bleeds over" to asynchronous call
- Dominant language
- PHP
- Stars
- 6.2k
- Forks
- 1.3k
- Avg merge
- 2h 53m
- Merged PRs (30d)
- 7
Description
### Describe the bug
We're running a small test suite of things after upgrading our aging S3 client library to this one. One of the things we've done is added asynchronous/parallel uploading with `putObjectAsync`, but our usages of `getObject` only ever fetch one object so we have that synchronous.
If we force a failure condition from `getObject` (such as fetching an object that doesn't exist), the next calls to any Promise-based functions throw a 'ghost' exception of the synchronous call, despite it not relating to any of the promises we're waiting on.
### Expected Behavior
No exception thrown
### Current Behavior
Exceptions thrown. Here's the exception log we're dealing with;
```
exception 'Aws\S3\Exception\S3Exception' with message 'Error executing "PutObject" on "https://s3.amazonaws.com/xxxxx.com/files/sigs/test-0.png"; AWS HTTP error: Unable to open "/var/www/xxxxx.com/public_html/files/sigs/test-get-successv2.png" using mode "w+": fopen(/var/www/xxxxx.com/public_html/files/sigs/test-get-successv2.png): Failed to open stream: Permission denied'
RuntimeException: Unable to open "/var/www/xxxxx.com/public_html/files/sigs/test-get-successv2.png" using mode "w+": fopen(/var/www/xxxxx.com/public_html/files/sigs/test-get-successv2.png): Failed to open stream: Permission denied in /var/www/xxxxx.com/public_html/vendor/guzzlehttp/psr7/src/Utils.php:361
Stack trace:
#0 [internal function]: GuzzleHttp\Psr7\Utils::GuzzleHttp\Psr7\{closure}()
#1 /var/www/xxxxx.com/public_html/vendor/guzzlehttp/psr7/src/Utils.php(373): fopen()
#2 /var/www/xxxxx.com/public_html/vendor/guzzlehttp/psr7/src/LazyOpenStream.php(47): GuzzleHttp\Psr7\Utils::tryFopen()
#3 /var/www/xxxxx.com/public_html/vendor/guzzlehttp/psr7/src/StreamDecoratorTrait.php(33): GuzzleHttp\Psr7\LazyOpenStream->createStream()
#4 /var/www/xxxxx.com/public_html/vendor/guzzlehttp/psr7/src/StreamDecoratorTrait.php(144): GuzzleHttp\Psr7\LazyOpenStream->__get()
#5 /var/www/xxxxx.com/public_html/vendor/guzzlehttp/guzzle/src/Handler/CurlFactory.php(414): GuzzleHttp\Psr7\LazyOpenStream->write()
#6 [internal function]: GuzzleHttp\Handler\CurlFactory::GuzzleHttp\Handler\{closure}()
#7 /var/www/xxxxx.com/public_html/vendor/guzzlehttp/guzzle/src/Handler/CurlMultiHandler.php(171): curl_multi_exec()
#8 /var/www/xxxxx.com/public_html/vendor/guzzlehttp/guzzle/src/Handler/CurlMultiHandler.php(189): GuzzleHttp\Handler\CurlMultiHandler->tick()
#9 /var/www/xxxxx.com/public_html/vendor/guzzlehttp/promises/src/Promise.php(251): GuzzleHttp\Handler\CurlMultiHandler->execute()
#10 /var/www/xxxxx.com/public_html/vendor/guzzlehttp/promises/src/Promise.php(227): GuzzleHttp\Promise\Promise->invokeWaitFn()
#11 /var/www/xxxxx.com/public_html/vendor/guzzlehttp/promises/src/Promise.php(272): GuzzleHttp\Promise\Promise->waitIfPending()
#12 /var/www/xxxxx.com/public_html/vendor/guzzlehttp/promises/src/Promise.php(229): GuzzleHttp\Promise\Promise->invokeWaitList()
#13 /var/www/xxxxx.com/public_html/vendor/guzzlehttp/promises/src/Promise.php(272): GuzzleHttp\Promise\Promise->waitIfPending()
#14 /var/www/xxxxx.com/public_html/vendor/guzzlehttp/promises/src/Promise.php(229): GuzzleHttp\Promise\Promise->invokeWaitList()
#15 /var/www/xxxxx.com/public_html/vendor/guzzlehttp/promises/src/Promise.php(69): GuzzleHttp\Promise\Promise->waitIfPending()
#16 /var/www/xxxxx.com/public_html/vendor/guzzlehttp/promises/src/Utils.php(121): GuzzleHttp\Promise\Promise->wait()
#17 /var/www/xxxxx.com/public_html/xxxxx/S3.php(228): GuzzleHttp\Promise\Utils::unwrap()
#18 /var/www/xxxxx.com/public_html/xxxxx/s3test.php(124): s3media->put_many()
#19 /var/www/xxxxx.com/public_html/xxxxx/s3test.php(62): task_s3test->testPutMany()
#20 /var/www/xxxxx.com/public_html/xxxxx/lab.php(461): task_s3test->runTask()
#21 /var/www/xxxxx.com/public_html/xxxxx/controller.php(25): module_lab->run()
#22 /var/www/xxxxx.com/public_html/xxxxx/controller.php(34): module_controller->check_special_modules()
#23 /var/www/xxxxx.com/public_html/index.php(13): module_controller->get_page()
#24 {main}
Next Aws\S3\Exception\S3Exception: Error executing "PutObject" on "https://s3.amazonaws.com/xxxxx.com/files/sigs/test-0.png"; AWS HTTP error: Unable to open "/var/www/xxxxx.com/public_html/files/sigs/test-get-successv2.png" using mode "w+": fopen(/var/www/xxxxx.com/public_html/files/sigs/test-get-successv2.png): Failed to open stream: Permission denied in /var/www/xxxxx.com/public_html/vendor/aws/aws-sdk-php/src/WrappedHttpHandler.php:196
Stack trace:
#0 /var/www/xxxxx.com/public_html/vendor/aws/aws-sdk-php/src/WrappedHttpHandler.php(98): Aws\WrappedHttpHandler->parseError()
#1 /var/www/xxxxx.com/public_html/vendor/guzzlehttp/promises/src/Promise.php(209): Aws\WrappedHttpHandler->Aws\{closure}()
#2 /var/www/xxxxx.com/public_html/vendor/guzzlehttp/promises/src/Promise.php(174): GuzzleHttp\Promise\Promise::callHandler()
#3 /var/www/xxxxx.com/public_html/vendor/guzzlehttp/promises/src/RejectedPromise.php(49): GuzzleHttp\Promise\Promise::GuzzleHttp\Promise\{closure}()
#4 /var/www/xxxxx.com/public_html/vendor/guzzlehttp/promises/src/TaskQueue.php(52): GuzzleHttp\Promise\RejectedPromise::GuzzleHttp\Promise\{closure}()
#5 /var/www/xxxxx.com/public_html/vendor/guzzlehttp/promises/src/Promise.php(238): GuzzleHttp\Promise\TaskQueue->run()
#6 /var/www/xxxxx.com/public_html/vendor/guzzlehttp/promises/src/Promise.php(272): GuzzleHttp\Promise\Promise->waitIfPending()
#7 /var/www/xxxxx.com/public_html/vendor/guzzlehttp/promises/src/Promise.php(229): GuzzleHttp\Promise\Promise->invokeWaitList()
#8 /var/www/xxxxx.com/public_html/vendor/guzzlehttp/promises/src/Promise.php(272): GuzzleHttp\Promise\Promise->waitIfPending()
#9 /var/www/xxxxx.com/public_html/vendor/guzzlehttp/promises/src/Promise.php(229): GuzzleHttp\Promise\Promise->invokeWaitList()
#10 /var/www/xxxxx.com/public_html/vendor/guzzlehttp/promises/src/Promise.php(69): GuzzleHttp\Promise\Promise->waitIfPending()
#11 /var/www/xxxxx.com/public_html/vendor/guzzlehttp/promises/src/Utils.php(121): GuzzleHttp\Promise\Promise->wait()
#12 /var/www/xxxxx.com/public_html/xxxxx/S3.php(228): GuzzleHttp\Promise\Utils::unwrap()
#13 /var/www/xxxxx.com/public_html/xxxxx/s3test.php(124): s3media->put_many()
#14 /var/www/xxxxx.com/public_html/xxxxx/s3test.php(62): task_s3test->testPutMany()
#15 /var/www/xxxxx.com/public_html/xxxxx/lab.php(461): task_s3test->runTask()
#16 /var/www/xxxxx.com/public_html/xxxxx/controller.php(25): module_lab->run()
#17 /var/www/xxxxx.com/public_html/xxxxx/controller.php(34): module_controller->check_special_modules()
#18 /var/www/xxxxx.com/public_html/index.php(13): module_controller->get_page()
#19 {main}
```
### Reproduction Steps
In our runTask, we're running two separate tasks: one is a get, which tries to get a file into a path it does not have permissions to write to, `test-get-successv2.png`. **This is supposed to fail, and is failing as expected.**
However, the next task is then supposed to do an unrelated `put_many` to paths that, when executed *without the get having run prior*, succeed with no errors. It is only when running with the `get` that the `put_many` then throws exceptions.
Our "get" function is very simple, only running this (with error checking, etc):
`return $this->s3->getObject($params);`
Our `put_many` is a bit more complex, but all it really does is do several `$this->s3->putObjectAsync`'s, puts them in an array, and then `\GuzzleHttp\Promise\Utils::unwrap`'s them. That unwrap is what's throwing the ghost exception from the prior `getObject`.
Note that the paths in the exception were not sent at all to `put_many`.
### Possible Solution
_No response_
### Additional Information/Context
_No response_
### SDK version used
3.275.1
### Environment details (Version of PHP (`php -v`)? OS name and version, etc.)
PHP 8.0, rest should be unrelated
Contributor guide
Assessment
This issue has not been assessed yet.