2

作为 AMP Socket 连接调用的一部分,我MultiReasonException在 DNS 查找过程中遇到了问题。抛出的实际异常是一个 NX 域,这很好 - 查找是针对当前关闭的主机。问题是我无法捕获和处理异常 - 它最终在我能够捕获它的循环级别结束但此时它没有用。

我试图在一个简单的测试脚本中重现以在此处发布,但如果我这样做,它可以正常工作:

Loop::run(function(){
 $res = yield \Amp\Dns\resolve("tp-link-hs110-5");
 var_dump($res);
}); 

并将其包装在 try catch 中,我能够捕获 DNS 异常——它甚至不会抛出MultiReasonException. 我认为这与我的实际应用程序有很多“并发”的事实有关,这意味着循环实际上会在等待 DNS 请求失败时停止并执行其他操作(“推迟”dns 查找协程) . 由于某种原因,这似乎导致异常被包裹在 aMultiReasonException中(xdebug 中的 Mutli 中仅列出了 1 个异常)。更重要的MultiReasonException是,它并没有被扔到我进行连接调用的协程中,它只是最终被扔到了Loop::run调用中——这是真正的问题。我无法在这里处理异常,因为它不在调用上下文中,并且可能来自代码中的任何地方。

任何人都可以帮助阐明这一点,或者甚至为我指出正确的方向以进一步确定这一点吗?我完全没主意了。试图通过大量的协程和占位符函数来追踪这个东西是一场噩梦。您到底是如何通过 AMP 堆栈调试这些东西的?

4

1 回答 1

1

如果其他人有类似的问题,我想我找到了自己问题的答案。

这是 Amp 堆栈如何处理异常的一个微妙之处。some我在高级函数中的 1 个或多个 Promise 上调用 amp函数。这作用于一个承诺链,最终导致一个进行 DNS 查找的函数。当 DNS 查找失败并抛出一个与 DNS 相关的异常(我没有在 Promise 中捕获)时,它会将 Promise 链渗透到某个地方,MultiReasonException即使它只有 1 个 Promise 正在执行,它似乎总是抛出一个。这意味着我总是得到一个MultiReasonException其中包含 DNS 异常。这很好,除了当我查看与 DNS 相关的异常的堆栈跟踪时,它当然不包含我的任何函数 - 所以我看不到它是如何被捕获的(我也没有尝试捕获它在源头,事实证明它会起作用,但从跟踪中看起来它不会)。

这是因为异常是在 amp 处于后续滴答时引发的,因此我的代码当前不在堆栈上。一旦异常被 AMP 堆栈中的代码抛出,异常中的跟踪当然会被锁定。然后它会被扔回我原来请求查找的承诺(生成器)中,它可能已经被捕获,但是因为我没有抓住它,它一直被抛出到some呼叫,在那里它以MultiReasonException.

我不确定这有多连贯,但也许它会对某人有所帮助。故事的寓意——不要试图变得聪明——只要抓住相关的异常,你就会产生将抛出它的承诺。异常堆栈跟踪可能会在 AMP 中产生误导。

于 2020-11-20T14:13:41.853 回答