1

数日前、ASP.NETMVCアプリケーションのElmahエラーログに次のエラーが表示され始めました。

プログラムを安全に実行し続けるにはスタックが不十分です。これは、呼び出しスタックに関数が多すぎるか、スタックスペースを使いすぎているスタックに関数があることが原因で発生する可能性があります。

問題のアプリケーションは、Webファーム内の2台のWindowsServer2012サーバーで実行されているマルチテナントWebアプリケーションです。エラーはいずれかのサーバーで定期的に(1時間に1回または2回)発生しますが、常に同じテナントのURLで発生します。同じ設定(テーマなど)で別のテナントを設定しましたが、エラーを再現できません。開発中に発生したことはありません。

例外とスタックトレースは、ある種の再帰関数が実行されていることを示しています。スタックトレースの開始時:

System.Web.HttpException(0x80004005):ハンドラー'System.Web.Mvc.HttpHandlerUtil+ServerExecuteHttpHandlerAsyncWrapper'の子要求の実行中にエラーが発生しました。---> System.Web.HttpException(0x80004005):ハンドラー'System.Web.Mvc.HttpHandlerUtil+ServerExecuteHttpHandlerAsyncWrapper'の子要求の実行中にエラーが発生しました。--->

これは、コールスタックの次のアイテムに到達する前に85回繰り返されます。

次に、次のようになります。

   at System.Runtime.CompilerServices.RuntimeHelpers.EnsureSufficientExecutionStack()
   at System.Web.Mvc.DefaultModelBinder.BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
   at System.Web.Mvc.ControllerActionInvoker.GetParameterValue(ControllerContext controllerContext, ParameterDescriptor parameterDescriptor)
   at System.Web.Mvc.ControllerActionInvoker.GetParameterValues(ControllerContext controllerContext, ActionDescriptor actionDescriptor)
   at System.Web.Mvc.Async.AsyncControllerActionInvoker.<>c__DisplayClass25.<BeginInvokeAction>b__1e(AsyncCallback asyncCallback, Object asyncState)
   at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResult`1.Begin(AsyncCallback callback, Object state, Int32 timeout)
   at System.Web.Mvc.Async.AsyncResultWrapper.Begin[TResult](AsyncCallback callback, Object state, BeginInvokeDelegate beginDelegate, EndInvokeDelegate`1 endDelegate, Object tag, Int32 timeout)
   at System.Web.Mvc.Async.AsyncResultWrapper.Begin[TResult](AsyncCallback callback, Object state, BeginInvokeDelegate beginDelegate, EndInvokeDelegate`1 endDelegate, Object tag)
   at System.Web.Mvc.Controller.<>c__DisplayClass1d.<BeginExecuteCore>b__17(AsyncCallback asyncCallback, Object asyncState)
   at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResult`1.Begin(AsyncCallback callback, Object state, Int32 timeout)
   at System.Web.Mvc.Async.AsyncResultWrapper.Begin[TResult](AsyncCallback callback, Object state, BeginInvokeDelegate beginDelegate, EndInvokeDelegate`1 endDelegate, Object tag, Int32 timeout)
   at System.Web.Mvc.Controller.BeginExecuteCore(AsyncCallback callback, Object state)
   at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResult`1.Begin(AsyncCallback callback, Object state, Int32 timeout)
   at System.Web.Mvc.Async.AsyncResultWrapper.Begin[TResult](AsyncCallback callback, Object state, BeginInvokeDelegate beginDelegate, EndInvokeDelegate`1 endDelegate, Object tag, Int32 timeout)
   at System.Web.Mvc.Async.AsyncResultWrapper.Begin(AsyncCallback callback, Object state, BeginInvokeDelegate beginDelegate, EndInvokeDelegate endDelegate, Object tag)
   at System.Web.Mvc.Controller.BeginExecute(RequestContext requestContext, AsyncCallback callback, Object state)
   at System.Web.Mvc.MvcHandler.<>c__DisplayClass8.<BeginProcessRequest>b__2(AsyncCallback asyncCallback, Object asyncState)
   at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResult`1.Begin(AsyncCallback callback, Object state, Int32 timeout)
   at System.Web.Mvc.Async.AsyncResultWrapper.Begin[TResult](AsyncCallback callback, Object state, BeginInvokeDelegate beginDelegate, EndInvokeDelegate`1 endDelegate, Object tag, Int32 timeout)
   at System.Web.Mvc.Async.AsyncResultWrapper.Begin(AsyncCallback callback, Object state, BeginInvokeDelegate beginDelegate, EndInvokeDelegate endDelegate, Object tag)
   at System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContextBase httpContext, AsyncCallback callback, Object state)
   at System.Web.Mvc.HttpHandlerUtil.ServerExecuteHttpHandlerWrapper.Wrap[TResult](Func`1 func)
   at System.Web.HttpServerUtility.ExecuteInternal(IHttpHandler handler, TextWriter writer, Boolean preserveForm, Boolean setPreviousPage, VirtualPath path, VirtualPath filePath, String physPath, Exception error, String queryStringOverride)
   at System.Web.HttpServerUtility.Execute(IHttpHandler handler, TextWriter writer, Boolean preserveForm, Boolean setPreviousPage)
   at System.Web.HttpServerUtilityWrapper.Execute(IHttpHandler handler, TextWriter writer, Boolean preserveForm)
   at System.Web.Mvc.Html.ChildActionExtensions.ActionHelper(HtmlHelper htmlHelper, String actionName, String controllerName, RouteValueDictionary routeValues, TextWriter textWriter)
   at System.Web.Mvc.Html.ChildActionExtensions.Action(HtmlHelper htmlHelper, String actionName, String controllerName, RouteValueDictionary routeValues)
   at ASP._Page_Themes_Clik_Views_Shared__Layout_cshtml.Execute() in c:\MySite\wwwroot\Themes\Clik\Views\Shared\_Layout.cshtml:line 15
   at System.Web.WebPages.WebPageBase.ExecutePageHierarchy()
   at System.Web.Mvc.WebViewPage.ExecutePageHierarchy()
   at System.Web.WebPages.WebPageBase.ExecutePageHierarchy(WebPageContext pageContext, TextWriter writer, WebPageRenderingBase startPage)
   at System.Web.WebPages.WebPageBase.RenderSurrounding(String partialViewName, Action`1 body)
   at System.Web.WebPages.WebPageBase.PopContext()
   at StackExchange.Profiling.MVCHelpers.ProfilingViewEngine.WrappedView.Render(ViewContext viewContext, TextWriter writer)
   at System.Web.Mvc.ViewResultBase.ExecuteResult(ControllerContext context)
   at System.Web.Mvc.ControllerActionInvoker.<>c__DisplayClass1a.<InvokeActionResultWithFilters>b__17()
   at System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilter(IResultFilter filter, ResultExecutingContext preContext, Func`1 continuation)
   at System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilter(IResultFilter filter, ResultExecutingContext preContext, Func`1 continuation)
   at System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilter(IResultFilter filter, ResultExecutingContext preContext, Func`1 continuation)
   at System.Web.Mvc.ControllerActionInvoker.InvokeActionResultWithFilters(ControllerContext controllerContext, IList`1 filters, ActionResult actionResult)
   at System.Web.Mvc.Async.AsyncControllerActionInvoker.<>c__DisplayClass25.<BeginInvokeAction>b__22(IAsyncResult asyncResult)
   at System.Web.Mvc.Controller.<>c__DisplayClass1d.<BeginExecuteCore>b__18(IAsyncResult asyncResult)
   at System.Web.Mvc.Async.AsyncResultWrapper.<>c__DisplayClass4.<MakeVoidDelegate>b__3(IAsyncResult ar)
   at System.Web.Mvc.Controller.EndExecuteCore(IAsyncResult asyncResult)
   at System.Web.Mvc.Async.AsyncResultWrapper.<>c__DisplayClass4.<MakeVoidDelegate>b__3(IAsyncResult ar)
   at System.Web.Mvc.MvcHandler.<>c__DisplayClass8.<BeginProcessRequest>b__3(IAsyncResult asyncResult)
   at System.Web.Mvc.Async.AsyncResultWrapper.<>c__DisplayClass4.<MakeVoidDelegate>b__3(IAsyncResult ar)
   at System.Web.Mvc.HttpHandlerUtil.ServerExecuteHttpHandlerWrapper.<>c__DisplayClass4.<Wrap>b__3()
   at System.Web.Mvc.HttpHandlerUtil.ServerExecuteHttpHandlerWrapper.Wrap[TResult](Func`1 func)
   at System.Web.HttpServerUtility.ExecuteInternal(IHttpHandler handler, TextWriter writer, Boolean preserveForm, Boolean setPreviousPage, VirtualPath path, VirtualPath filePath, String physPath, Exception error, String queryStringOverride)
   at System.Web.HttpServerUtility.ExecuteInternal(IHttpHandler handler, TextWriter writer, Boolean preserveForm, Boolean setPreviousPage, VirtualPath path, VirtualPath filePath, String physPath, Exception error, String queryStringOverride)
   at System.Web.HttpServerUtility.Execute(IHttpHandler handler, TextWriter writer, Boolean preserveForm, Boolean setPreviousPage)
   at System.Web.HttpServerUtilityWrapper.Execute(IHttpHandler handler, TextWriter writer, Boolean preserveForm)
   at System.Web.Mvc.Html.ChildActionExtensions.ActionHelper(HtmlHelper htmlHelper, String actionName, String controllerName, RouteValueDictionary routeValues, TextWriter textWriter)
   at System.Web.Mvc.Html.ChildActionExtensions.Action(HtmlHelper htmlHelper, String actionName, String controllerName, RouteValueDictionary routeValues)
   at ASP._Page_Themes_Clik_Views_Shared__Layout_cshtml.Execute() in c:\MySite\wwwroot\Themes\Clik\Views\Shared\_Layout.cshtml:line 15

からのスタックトレース:

ASP._Page_Themes_Clik_Views_Shared__Layout_cshtml.Execute()in c:\ MySite \ wwwroot \ Themes \ Clik \ Views \ Shared_Layout.cshtml:line 15
at System.Web.WebPages.WebPageBase.ExecutePageHierarchy()at System.Web.Mvc.WebViewPage.ExecutePageHierarchy ()

ビューがそれ自体を再帰的に実行しているかのように、同様に85回繰り返されます。

それが指すコード行は、次の呼び出しHtml.Actionです。

public MvcHtmlString Menu(string name, string overrideView = null)
{
    Ensure.Argument.NotNullOrEmpty(name, "name");
    return html.Action("_details", "menus", new { name = name, viewName = overrideView });
}

これは、サイトナビゲーションメニューを表示するために他のすべてのテナントおよびテーマで使用されるのと同じコードです。MenusController

[HttpGet]
public async Task<ActionResult> Details(string name)
{
    var menu = await menusClient.GetMenuByName(
        siteId: siteContext.SiteId,
        name: name
    )
    .ConfigureAwait(false);

    if (menu == null)
    {
        return HttpNotFound();
    }

    var model = Mapper.Map<MenuDetailsModel>(menu);
    model.SetCurrentMenuItem(Request.Url);           
    return View("Details", model);
}

#region Widget 

[HttpGet, ChildActionOnly]
public ActionResult _Details(string name)
{
    return Details(name).Result; // this is converted to a partial view result by an action filter
}

ASP.NET MVCは非同期の子アクションをサポートしていないため、で非同期アクションをブロックする必要があります_Details。ViewResultをからに変換するアクションフィルターがあることに注意してDetailsくださいPartialViewResult

私が言ったように、このコードは開発と本番環境で(ほとんど常に)うまく機能します。内部で例外をスローしようとしましMenusControllerたが、それでも例外を複製できません。

4

1 に答える 1

0

これを試して:

public static MvcHtmlString Menu(this HtmlHelper helper, string name, string overrideView = null)
{
    var url = new UrlHelper(htmlHelper.ViewContext.RequestContext);
    Ensure.Argument.NotNullOrEmpty(name, "name");
    return url.Action("_details", "menus", new { name = name, viewName = overrideView });
}
于 2013-10-04T05:12:48.817 に答える