suin.io

register_shutdown_function()はFatal後でも動く

suin2011年3月19日

register_shutdown_function()で登録したコールバック関数が、実行時にFatalになった時でも動くのか試してみた。

ケース1: メモリを使い切った場合

メモリを使い切るまで、配列を足し続けるコードを書いた。メモリオーバのエラーで落ちても、コールバック関数は呼ばれた。

<?php
error_reporting(-1);
ini_set('display_errors', 1);

register_shutdown_function('unexpected_shutdown');

function unexpected_shutdown()
{
	echo '予期しないシャットダウンです。';
}

while ( true ) // メモリを使い切るまでループ
{
	$hugeData[] = array();
}

// 結果:
// Fatal error: Allowed memory size of 33554432 bytes exhausted (tried to allocate 40 bytes) in /Applications/MAMP/htdocs/php/register_shutdown_function/case1.php on line 15
// 予期しないシャットダウンです。

ただ、これもコールバック関数を実行するのに十分なメモリがあるときだけ成功するみたい。コールバック関数内でメモリを大量消費すると、当然こけちゃう。コールバック関数で、メモリを沢山必要とする場合は、unset()できるものはしてメモリ領域を確保しないとダメっぽい。

<?php

error_reporting(-1);
ini_set('display_errors', 1);

register_shutdown_function('unexpected_shutdown');

function unexpected_shutdown()
{
	$dummy = range(0, 1000); // ここでメモリオーバ
	echo '予期しないシャットダウンです。';
}

while ( true )
{
	$hugeData[] = array();
}

// 結果:
// Fatal error: Allowed memory size of 33554432 bytes exhausted (tried to allocate 40 bytes) in /Applications/MAMP/htdocs/php/register_shutdown_function/case1.1.php on line 16

ケース2: 構文エラーの外部ファイルをincludeした場合

この場合もコールバック関数が動いた。

<?php

error_reporting(-1);
ini_set('display_errors', 1);

register_shutdown_function('unexpected_shutdown');

function unexpected_shutdown()
{
	echo '予期しないシャットダウンです。';
}

require 'parse_error.php'; // syntax error のファイル

echo 'OK'; // これを表示する前に落ちる

// 結果: 
// Parse error: syntax error, unexpected T_STRING in /Applications/MAMP/htdocs/php/register_shutdown_function/parse_error.php on line 3
// 予期しないシャットダウンです。

register_shutdown_function()を使えば、せめてHTTP 503エラーくらい出せるかも。

RELATED POSTS