gabrielelana/graceful-death

一个允许您捕获致命错误的库

0.7.4 2014-08-12 09:14 UTC

This package is auto-updated.

Last update: 2024-09-08 06:34:21 UTC


README

如您所知,在PHP中捕获致命错误非常痛苦,几乎是不可能的。这是一个(部分)解决这个问题库的库

使用方法

<?php

require __DIR__ . "/vendor/autoload.php";

// The output will be:
//
// Yes, I can ;-)

GracefulDeath::around(function() {
    try {
        // Avoid to print the error in order to have clean output, don't try this at home :-)
        error_reporting(E_ALL ^ E_ERROR);
        // Creating an instance of an unknown class will cause a fatal error
        new UnknownClass();
    } catch(Exception $e) {
        // A fatal error is uncatchable
        echo "You cannot catch this, AHAHAHAHA!!!\n";
    }
})
->afterViolentDeath("Yes, I can ;-)\n")
->run();

场景

您有一段可能会引发致命错误的代码,并且希望能够在它之后进行清理或根据某些策略重新尝试。使用GracefulDeath,您可以将这段代码放入闭包中,并将其作为参数传递给GracefulDeath::around静态方法。这个静态方法返回一个构建器实例,让您配置GracefulDeath的行为。使用afterViolentDeath,您可以为每次触发致命错误时调用的处理程序进行配置。处理程序可以是:

  • 一个整数:进程将以这个状态码退出
  • 一个字符串:这个字符串将被打印到标准输出(如下例所示)
  • 一个闭包:闭包将被执行,其返回值将被用作run方法的返回值。闭包的签名是function($status, $stdout, $stderr),其中$status是传递给GracefulDeath::around的代码的退出状态

还有一些其他方法可以用来配置GracefulDeath

  • afterNaturalDeath:与afterViolentDeath类似,但用于配置一个仅在未触发错误时调用的处理程序

  • afterDeath:用于配置一个处理程序(如afterViolentDeathafterNaturalDeath),在传递给GracefulDeath::around的代码终止后调用

  • reanimationPolicy:用于配置重新激活策略,即用于决定在致命错误之后是否应该再次执行传递给GracefulDeath::around的代码的策略。重新激活策略可以是:

    • 一个布尔值:如果为true,则将无限重试,如果为false,则永远不会重试(默认值)
    • 一个整数:代码将被执行的次数。如果代码没有错误终止或者执行次数超过了传递的参数,则代码将不会再次执行
    • 一个闭包:如果闭包返回true,则代码将被再次执行。闭包的签名是function($status, $attempts, $stdout, $stderr)
      • $status:传递给GracefulDeath::around的代码的退出状态
      • $attempts:代码已被执行的次数(想想之前的生命),从1开始
      • $stdout:传递给GracefulDeath::around的代码在stdout上打印的内容
      • $stderr:传递给GracefulDeath::around的代码在stderr上打印的内容

    有一些现成的重新激活策略可供使用

    • doNotReanimate:这是默认行为,因此不太有用,但可用于文档或使代码更明确
    • giveMeAnotherChance:将只重新激活子进程一次
    • liveForever:将始终重新激活子进程。如果您使用此重新激活策略,请务必还使用avoidFutileMedicalCare以避免不断重新激活一个破损的子进程
  • doNotCaptureOutput:避免捕获stdoutstderr。请注意,如果没有捕获输出,则无法将其提供给reanimationPolicy闭包

  • doNotEchoOutput:丢弃(如果有)捕获的输出

  • avoidFutileMedicalCare($numberOfFailures, $inAmountOfTime):避免在短时间内($inAmountOfTime 默认为 60 秒)多次复活已经多次死亡的过程($numberOfFailures 默认为 6)

有关所有选项和方法,请参阅示例或测试 😄

使用案例

  • 您有一个运行时间长的进程,该进程会泄露内存(参见 examples/memory_leak.php
  • 您可以使用 graceful-death 作为 supervisor,为此请使用 ->liveForever() 以便始终复活子进程,并且不要忘记使用 ->avoidFutileMedicalCare() 以避免不断复活一个损坏的子进程

它是如何工作的?

当调用 run 时,进程会进行分支,子进程将执行传递给 GracefulDeath::around 的代码,父进程将作为子进程的监督者。监督者将等待子进程死亡,并根据退出状态和给定配置采取相应行动。

注意事项

它只适用于有 pcntl_* 函数的地方。

自我推广

如果您喜欢这个项目,那么请考虑