Browse Source

Fix #12168 - Stream restores error handler even if wrapper throws exception

Glen Sawyer 7 years ago
parent
commit
fe97f0650a

+ 5 - 2
src/Http/Client/Adapter/Stream.php

@@ -306,8 +306,11 @@ class Stream
         set_error_handler(function ($code, $message) {
             $this->_connectionErrors[] = $message;
         });
-        $this->_stream = fopen($url, 'rb', false, $this->_context);
-        restore_error_handler();
+        try {
+            $this->_stream = fopen($url, 'rb', false, $this->_context);
+        } finally {
+            restore_error_handler();
+        }
 
         if (!$this->_stream || !empty($this->_connectionErrors)) {
             throw new Exception(implode("\n", $this->_connectionErrors));

+ 30 - 0
tests/TestCase/Http/Client/Adapter/StreamTest.php

@@ -35,6 +35,10 @@ class CakeStreamWrapper implements \ArrayAccess
 
     public function stream_open($path, $mode, $options, &$openedPath)
     {
+        if ($path == 'http://throw_exception/') {
+            throw new \Exception;
+        }
+
         $query = parse_url($path, PHP_URL_QUERY);
         if ($query) {
             parse_str($query, $this->_query);
@@ -152,6 +156,32 @@ class StreamTest extends TestCase
     }
 
     /**
+     * Test stream error_handler cleanup when wrapper throws exception
+     *
+     * @return void
+     */
+    public function testSendWrapperException()
+    {
+        $stream = new Stream();
+        $request = new Request('http://throw_exception/');
+
+        $currentHandler = set_error_handler(function () {
+        });
+        restore_error_handler();
+
+        try {
+            $stream->send($request, []);
+        } catch (\Exception $e) {
+        }
+
+        $newHandler = set_error_handler(function () {
+        });
+        restore_error_handler();
+
+        $this->assertEquals($currentHandler, $newHandler);
+    }
+
+    /**
      * Test building the context headers
      *
      * @return void