为什么IIS会给广泛的" 502.3 - Bad Gateway"循环构造函数的错误

时间:2017-10-18 19:38:25

标签: c# asp.net iis asp.net-core-2.0 .net-core-2.0

我明白为什么代码无法正常工作。我不明白技术原因是什么,所以我们不会得到更明确的错误消息。

在开发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();
    }
}

令人惊讶的是,在应用程序崩溃之前,IIS给了我一个502.3 - Bad Gateway错误,而不是堆栈溢出异常,而这并没有提供有关底层问题的大量信息。我希望像这样的循环调用是一个容易检测的模式,它不仅可以被编译器捕获,而且甚至可以被VisualStudio 2017或Resharper终极针对,但没有任何事情警告过我。

this article以及this one似乎表明问题可能是超时但似乎不太可能,因为应用程序会在两秒钟内崩溃。

我根本不明白为什么没有CircularConstructionException - 这听起来很容易实现,更糟糕的是,为什么IIS没有像在线编译器一样抛出常规StackOverflowException

3 个答案:

答案 0 :(得分:3)

我相信正确的答案是它是C#的设计决定。在您的情况下,其他异常被捕获并包装在异常页面中,StackOverflowException会导致进程终止,这是报告502.3响应(报告连接失败)的原因。

StackOverflowException s上的MSDN页面:

  

在.NET的早期版本中   框架,您的应用程序可以   捕获StackOverflowException对象   (例如,从中恢复   无限递归)。但是,那   目前气馁   因为重要的额外代码是   需要可靠地捕获堆栈   溢出异常并继续   程序执行

     

从.NET Framework开始   版本2.0,StackOverflowException   try-catch无法捕获对象   块和相应的过程是   默认终止。因此,   建议用户编写代码   检测和防止堆栈   溢出。例如,如果你的   应用程序取决于递归,使用   反击或国家条件   终止递归循环。注意   托管的应用程序   公共语言运行库(CLR)可以   指定CLR卸载   应用程序域所在的堆栈   溢出异常发生并让   相应的过程继续。对于   更多信息,请参阅   ICLRPolicyManager接口和   托管公共语言运行时。

答案 1 :(得分:2)

  

我根本不明白为什么没有CircularConstructionException - 这听起来很容易实现

在运行时,对于实例化另一个对象的对象,即使是相同类型,也没有任何违法行为。问题是您没有正确控制堆栈,因此StackOverflowException实际上是合适的。在这种情况下,可以说编译器可以检测到该问题,但这仍然不是运行时异常。

  

更糟糕的是,为什么IIS不像在线编译器那样抛出常规的StackOverflowException?

IIS可能不知道为什么它会死亡。它创建了一个工作进程来运行您的应用程序;该进程因堆栈溢出而死亡。然后,IIS主机进程返回错误,指示工作进程失败。也许“Bad Gateway”不是最明确的,但是IIS主机对堆栈溢出一无所知。它只是知道它的工作进程没有响应或死亡。

答案 2 :(得分:0)

此类调用itsef不定时并导致堆栈溢出

public class B
{
    public B()
    {
        var b = new B();
    }
}