Skip to content

Commit c770f77

Browse files
authored
fix: reset fatal error handler when starting a new context (#2128)
1 parent a148d55 commit c770f77

7 files changed

Lines changed: 87 additions & 4 deletions

File tree

.github/workflows/ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ jobs:
8181

8282
- name: Remove OpenTelemetry dependencies on unsupported PHP versions
8383
if: ${{ matrix.php.version == '7.2' || matrix.php.version == '7.3' || matrix.php.version == '7.4' || matrix.php.version == '8.0' }}
84-
run: composer remove open-telemetry/api open-telemetry/exporter-otlp open-telemetry/sdk --dev --no-interaction --no-update
84+
run: composer remove open-telemetry/api open-telemetry/exporter-otlp open-telemetry/sem-conv open-telemetry/sdk --dev --no-interaction --no-update
8585

8686
- name: Set phpunit/phpunit version constraint
8787
run: composer require phpunit/phpunit:'${{ matrix.php.phpunit }}' --dev --no-interaction --no-update

composer.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
"nyholm/psr7": "^1.8",
4040
"open-telemetry/api": "^1.0",
4141
"open-telemetry/exporter-otlp": "^1.0",
42+
"open-telemetry/sem-conv": "^1.27",
4243
"open-telemetry/sdk": "^1.0",
4344
"phpstan/phpstan": "^1.3",
4445
"phpunit/phpunit": "^8.5.52|^9.6.34",

src/ErrorHandler.php

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,11 @@ final class ErrorHandler
117117
*/
118118
private static $reservedMemory;
119119

120+
/**
121+
* @var int The amount of memory to reserve for the fatal error handler
122+
*/
123+
private static $reservedMemorySize = self::DEFAULT_RESERVED_MEMORY_SIZE;
124+
120125
/**
121126
* @var bool Whether the fatal error handler should be disabled
122127
*/
@@ -214,6 +219,7 @@ public static function registerOnceFatalErrorHandler(int $reservedMemorySize = s
214219
}
215220

216221
self::$handlerInstance->isFatalErrorHandlerRegistered = true;
222+
self::$reservedMemorySize = $reservedMemorySize;
217223
self::$reservedMemory = str_repeat('x', $reservedMemorySize);
218224

219225
register_shutdown_function(\Closure::fromCallable([self::$handlerInstance, 'handleFatalError']));
@@ -301,6 +307,19 @@ public function setMemoryLimitIncreaseOnOutOfMemoryErrorInBytes(?int $valueInByt
301307
$this->memoryLimitIncreaseOnOutOfMemoryErrorValue = $valueInBytes;
302308
}
303309

310+
/**
311+
* @internal
312+
*/
313+
public static function resetFatalErrorHandlerState(): void
314+
{
315+
self::$disableFatalErrorHandler = false;
316+
self::$didIncreaseMemoryLimit = false;
317+
318+
if (self::$handlerInstance !== null && self::$handlerInstance->isFatalErrorHandlerRegistered) {
319+
self::$reservedMemory = str_repeat('x', self::$reservedMemorySize);
320+
}
321+
}
322+
304323
/**
305324
* Handles errors by capturing them through the client according to the
306325
* configured bit field.

src/State/RuntimeContextManager.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
use Psr\Log\LoggerInterface;
88
use Psr\Log\NullLogger;
9+
use Sentry\ErrorHandler;
910
use Sentry\Tracing\PropagationContext;
1011

1112
/**
@@ -113,6 +114,8 @@ public function startContext(): void
113114
return;
114115
}
115116

117+
ErrorHandler::resetFatalErrorHandlerState();
118+
116119
$this->createContextForExecutionContextKey($executionContextKey);
117120
}
118121

tests/Fixtures/OpenTelemetry/TestDiscoveryStrategy.php

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
namespace Sentry\Tests\Fixtures\OpenTelemetry;
66

7+
use GuzzleHttp\Psr7\HttpFactory;
78
use Nyholm\Psr7\Factory\Psr17Factory;
89
use Psr\Http\Client\ClientInterface;
910
use Psr\Http\Message\RequestFactoryInterface;
@@ -21,7 +22,10 @@ public static function getCandidates(string $type): array
2122
}
2223

2324
if (is_a(RequestFactoryInterface::class, $type, true) || is_a(StreamFactoryInterface::class, $type, true)) {
24-
return [['class' => Psr17Factory::class, 'condition' => Psr17Factory::class]];
25+
return [
26+
['class' => HttpFactory::class, 'condition' => HttpFactory::class],
27+
['class' => Psr17Factory::class, 'condition' => Psr17Factory::class],
28+
];
2529
}
2630

2731
return [];

tests/Integration/OTLPIntegrationTest.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -280,10 +280,10 @@ private function useCapturingHttpClient(): void
280280

281281
if (method_exists(HttpClientDiscovery::class, 'setDiscoverers')) {
282282
HttpClientDiscovery::setDiscoverers([new TestClientDiscoverer()]);
283-
} else {
284-
ClassDiscovery::prependStrategy(TestDiscoveryStrategy::class);
285283
}
286284

285+
ClassDiscovery::prependStrategy(TestDiscoveryStrategy::class);
286+
287287
StubOtelHttpClient::reset();
288288
}
289289

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
--TEST--
2+
Test that resetting the fatal error handler state re-arms OOM handling
3+
--FILE--
4+
<?php
5+
6+
declare(strict_types=1);
7+
8+
namespace Sentry\Tests;
9+
10+
use Sentry\ErrorHandler;
11+
12+
$vendor = __DIR__;
13+
14+
while (!file_exists($vendor . '/vendor')) {
15+
$vendor = \dirname($vendor);
16+
}
17+
18+
require $vendor . '/vendor/autoload.php';
19+
20+
error_reporting(\E_ALL & ~\E_DEPRECATED & ~\E_USER_DEPRECATED);
21+
22+
function getErrorHandlerProperty(string $name): \ReflectionProperty
23+
{
24+
$property = new \ReflectionProperty(ErrorHandler::class, $name);
25+
$property->setAccessible(true);
26+
27+
return $property;
28+
}
29+
30+
function setErrorHandlerStaticProperty(string $name, $value): void
31+
{
32+
getErrorHandlerProperty($name)->setValue(null, $value);
33+
}
34+
35+
function getErrorHandlerStaticProperty(string $name)
36+
{
37+
return getErrorHandlerProperty($name)->getValue();
38+
}
39+
40+
ErrorHandler::registerOnceFatalErrorHandler(1234);
41+
42+
setErrorHandlerStaticProperty('disableFatalErrorHandler', true);
43+
setErrorHandlerStaticProperty('didIncreaseMemoryLimit', true);
44+
setErrorHandlerStaticProperty('reservedMemory', null);
45+
46+
ErrorHandler::resetFatalErrorHandlerState();
47+
48+
var_dump(getErrorHandlerStaticProperty('disableFatalErrorHandler'));
49+
var_dump(getErrorHandlerStaticProperty('didIncreaseMemoryLimit'));
50+
var_dump(\strlen(getErrorHandlerStaticProperty('reservedMemory')));
51+
52+
?>
53+
--EXPECT--
54+
bool(false)
55+
bool(false)
56+
int(1234)

0 commit comments

Comments
 (0)