15
15
use Psr \Log \LoggerInterface ;
16
16
use Symfony \Component \Debug \Exception \ContextErrorException ;
17
17
use Symfony \Component \Debug \Exception \FatalErrorException ;
18
+ use Symfony \Component \Debug \Exception \OutOfMemoryException ;
18
19
use Symfony \Component \Debug \FatalErrorHandler \UndefinedFunctionFatalErrorHandler ;
19
20
use Symfony \Component \Debug \FatalErrorHandler \UndefinedMethodFatalErrorHandler ;
20
21
use Symfony \Component \Debug \FatalErrorHandler \ClassNotFoundFatalErrorHandler ;
@@ -53,8 +54,6 @@ class ErrorHandler
53
54
54
55
private $ displayErrors ;
55
56
56
- private $ caughtOutput = 0 ;
57
-
58
57
/**
59
58
* @var LoggerInterface[] Loggers for channels
60
59
*/
@@ -64,8 +63,6 @@ class ErrorHandler
64
63
65
64
private static $ stackedErrorLevels = array ();
66
65
67
- private static $ fatalHandler = false ;
68
-
69
66
/**
70
67
* Registers the error handler.
71
68
*
@@ -119,16 +116,6 @@ public static function setLogger(LoggerInterface $logger, $channel = 'deprecatio
119
116
self ::$ loggers [$ channel ] = $ logger ;
120
117
}
121
118
122
- /**
123
- * Sets a fatal error exception handler.
124
- *
125
- * @param callable $handler An handler that will be called on FatalErrorException
126
- */
127
- public static function setFatalErrorExceptionHandler ($ handler )
128
- {
129
- self ::$ fatalHandler = $ handler ;
130
- }
131
-
132
119
/**
133
120
* @throws ContextErrorException When error_reporting returns error
134
121
*/
@@ -284,7 +271,7 @@ public function handleFatal()
284
271
throw $ exception ;
285
272
}
286
273
287
- if (!$ error || !$ this ->level || !in_array ($ error ['type ' ], array (E_ERROR , E_CORE_ERROR , E_COMPILE_ERROR , E_PARSE ))) {
274
+ if (!$ error || !$ this ->level || !($ error ['type ' ] & (E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR | E_PARSE ))) {
288
275
return ;
289
276
}
290
277
@@ -298,7 +285,7 @@ public function handleFatal()
298
285
self ::$ loggers ['emergency ' ]->emergency ($ error ['message ' ], $ fatal );
299
286
}
300
287
301
- if ($ this ->displayErrors && ( $ exceptionHandler || self :: $ fatalHandler ) ) {
288
+ if ($ this ->displayErrors && $ exceptionHandler ) {
302
289
$ this ->handleFatalError ($ exceptionHandler , $ error );
303
290
}
304
291
}
@@ -327,82 +314,25 @@ private function handleFatalError($exceptionHandler, array $error)
327
314
328
315
$ level = isset ($ this ->levels [$ error ['type ' ]]) ? $ this ->levels [$ error ['type ' ]] : $ error ['type ' ];
329
316
$ message = sprintf ('%s: %s in %s line %d ' , $ level , $ error ['message ' ], $ error ['file ' ], $ error ['line ' ]);
330
- $ exception = new FatalErrorException ($ message , 0 , $ error ['type ' ], $ error ['file ' ], $ error ['line ' ], 3 );
331
-
332
- foreach ($ this ->getFatalErrorHandlers () as $ handler ) {
333
- if ($ e = $ handler ->handleError ($ error , $ exception )) {
334
- $ exception = $ e ;
335
- break ;
336
- }
337
- }
338
-
339
- // To be as fail-safe as possible, the FatalErrorException is first handled
340
- // by the exception handler, then by the fatal error handler. The latter takes
341
- // precedence and any output from the former is cancelled, if and only if
342
- // nothing bad happens in this handling path.
343
-
344
- $ caughtOutput = 0 ;
345
-
346
- if ($ exceptionHandler ) {
347
- $ this ->caughtOutput = false ;
348
- ob_start (array ($ this , 'catchOutput ' ));
349
- try {
350
- call_user_func ($ exceptionHandler , $ exception );
351
- } catch (\Exception $ e ) {
352
- // Ignore this exception, we have to deal with the fatal error
353
- }
354
- if (false === $ this ->caughtOutput ) {
355
- ob_end_clean ();
356
- }
357
- if (isset ($ this ->caughtOutput [0 ])) {
358
- ob_start (array ($ this , 'cleanOutput ' ));
359
- echo $ this ->caughtOutput ;
360
- $ caughtOutput = ob_get_length ();
361
- }
362
- $ this ->caughtOutput = 0 ;
363
- }
364
-
365
- if (self ::$ fatalHandler ) {
366
- try {
367
- call_user_func (self ::$ fatalHandler , $ exception );
368
-
369
- if ($ caughtOutput ) {
370
- $ this ->caughtOutput = $ caughtOutput ;
371
- }
372
- } catch (\Exception $ e ) {
373
- if (!$ caughtOutput ) {
374
- // Neither the exception nor the fatal handler succeeded.
375
- // Let PHP handle that now.
376
- throw $ exception ;
317
+ if (0 === strpos ($ error ['message ' ], 'Allowed memory ' ) || 0 === strpos ($ error ['message ' ], 'Out of memory ' )) {
318
+ $ exception = new OutOfMemoryException ($ message , 0 , $ error ['type ' ], $ error ['file ' ], $ error ['line ' ], 3 , false );
319
+ } else {
320
+ $ exception = new FatalErrorException ($ message , 0 , $ error ['type ' ], $ error ['file ' ], $ error ['line ' ], 3 , true );
321
+
322
+ foreach ($ this ->getFatalErrorHandlers () as $ handler ) {
323
+ if ($ e = $ handler ->handleError ($ error , $ exception )) {
324
+ $ exception = $ e ;
325
+ break ;
377
326
}
378
327
}
379
328
}
380
- }
381
-
382
- /**
383
- * @internal
384
- */
385
- public function catchOutput ($ buffer )
386
- {
387
- $ this ->caughtOutput = $ buffer ;
388
329
389
- return '' ;
390
- }
391
-
392
- /**
393
- * @internal
394
- */
395
- public function cleanOutput ($ buffer )
396
- {
397
- if ($ this ->caughtOutput ) {
398
- // use substr_replace() instead of substr() for mbstring overloading resistance
399
- $ cleanBuffer = substr_replace ($ buffer , '' , 0 , $ this ->caughtOutput );
400
- if (isset ($ cleanBuffer [0 ])) {
401
- $ buffer = $ cleanBuffer ;
402
- }
330
+ try {
331
+ call_user_func ($ exceptionHandler , $ exception );
332
+ } catch (\Exception $ e ) {
333
+ // The handler failed. Let PHP handle that now.
334
+ throw $ exception ;
403
335
}
404
-
405
- return $ buffer ;
406
336
}
407
337
}
408
338
0 commit comments