Подобную проблему я решал при помощи стандартного перехвата буфера вывода (ob_start...). Фокус в том, что обработчик буфера вызывается даже в случае фатальных ошибок (указанных вами), таким образом проверив в обработчике буфера, не произошла ли ошибка, мы уже можем слать нужные заголовки и т.д.
ob_start('ob_end');
...
function ob_end($outputData)
{
$error = error_get_last();
if (is_array($error) && in_array($error['type'], array(E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR)))
{
/* Фатальная ошибка, отдаем 500 */
}
return $outputData;
}