为什么IIS在循环构造函数中给出了广泛的“502.3 - Bad Gateway”错误
我明白为什么代码不能工作。我不明白是什么技术原因造成的,所以我们没有得到更明确的错误信息。为什么IIS在循环构造函数中给出了广泛的“502.3 - Bad Gateway”错误
在开发netcore2应用程序时,我最终使用构造函数进行循环引用。我的意思是类A的构造函数实例化了另一个类型为B的对象,它本身会实例化一个类型为A的对象等等。
这是一个简单的代码片段,用于重现圆形实例化,该实例在online compiler上引发StackOverflowException
我做了这个例子。
public class A
{
public A()
{
var b = new B();
}
}
public class B
{
public B()
{
var b = new B();
}
}
public class Program
{
public static void Main(string[] args)
{
var a = new A();
}
}
令人惊讶,而不是一个计算器例外它是一个502.3 - Bad Gateway
错误IIS给我的应用程序崩溃,这并没有给有关基本问题的大量信息之前。我期望这样的循环调用可以轻松地检测到它不仅被编译器捕获,而且甚至可以被VisualStudio 2017或Resharper最终指出,但没有任何警告我。
this article以及this one似乎表明问题可能是暂停,但似乎不大可能,因为应用程序在两秒钟内崩溃。
我简直不明白为什么没有CircularConstructionException
- 这听起来很容易实现,甚至更糟糕的是,为什么IIS没有像联机编译器那样抛出常规StackOverflowException
?
我相信正确的答案是它是C#的设计决定。鉴于其他例外情况在您的案例的例外页中被捕获并包装,StackOverflowException
会导致进程终止,这是报告502.3响应(报告连接失败)的原因。
从MSDN页面上StackOverflowException S:
在.NET框架 以前的版本,您的应用程序可以 赶上StackOverflowException对象 (例如,从 无限递归恢复)。然而, 做法是目前气馁 因为显著的额外代码可靠赶上一个堆栈溢出 异常并继续 执行程序需要 。
与.NET Framework 2.0版本开始,StackOverflowException 对象不能由一个try-catch 块捕获和相应的过程是 默认终止。因此, 建议用户编写他们的代码 来检测并防止堆栈 溢出。例如,如果您的 应用程序依赖于递归,请使用 计数器或状态条件来终止递归循环。注意 承载公共语言运行时(CLR)的应用程序可以指定CLR卸载发生堆栈 溢出异常的应用程序域,并让相应的进程继续。有关 的更多信息,请参阅 ICLRPolicyManager接口和 承载公共语言运行时。
非常感谢您指向相应MSDN页面的指针。所以它确实是这样的。我将深入研究MSDN页面提到的ICLRPolicyManager。 – Wndrr
该类调用itsef不定式时间和造成堆栈溢出
public class B
{
public B()
{
var b = new B();
}
}
你的陈述是真实的,但是这并不回答这个问题。无论如何感谢您的时间:-) – Wndrr
我只是不明白为什么没有CircularConstructionException - 这听起来很容易的实现
有在运行时关于实例化另一个对象的对象甚至是相同类型的对象都不是非法的。问题是你没有正确控制堆栈,所以StackOverflowException
实际上是合适的。在这种情况下,可以说这个问题可以被编译器检测到,但这仍然不是运行时异常。
甚至更糟糕的是,为什么不是IIS像联机编译器一样抛出常规的StackOverflowException?
IIS可能不知道为什么它死了。它创建一个工作进程来运行你的应用程序;该进程因堆栈溢出而死亡。 IIS主机进程然后返回一个错误,指示工作进程失败。也许“坏的网关”不是最清楚的,但IIS主机不知道堆栈溢出。它只知道它的工作进程没有响应或死机。
感谢您对IIS内部行为的进一步解释。我希望我能标出两个答案是正确的。 – Wndrr
502.3也不例外。实际的异常很可能是StackOverflowException。 502.3甚至可能不是来自IIS--它可能来自您和IIS之间的代理。 –
我不知道它是否重要,但这是在本地,在调试模式。对于抛出的其他异常,我会得到一个包含详细信息的异常页面。为什么在这种情况下只能隐藏异常?我有点理解为什么应用程序崩溃(无法摆脱循环),但为什么是StackOverflow或任何异常实际上是由IIS在调试模式下隐藏的? – Wndrr