简体   繁体   中英

Stack overflow in a child thread blocks parent thread

I have an ASP.NET Core 3.1 MVC application. In my controller, I am performing XSLT transformation. I have a transformation that is causing stack overflow exception, shutting my whole (VS-hosted) server down.

I know what is wrong with my transformation, so I do not want to fix it (I'll do it later), for now I want to be able to correctly handle scenarios where a stack overflow causes unpredicated behavior. My idea is to create a new child thread, and in this thread process the XSLT, if the thread runs for too long, I would like to kill it in the parent thread.

Now that's for theory, in practice, when I do this, parent thread gets locked out, debugger is not moving forward and everything crashes. Below is one of many examples of code that I have tried - I tried Task.Run() and CancellationToken approach, I tried it with Task.Wait(1000) , I tried new Thread(()=>MyFunction()) approach, I tried calling xslt.Transform() as you see below, but I also tried to wrap 100% of transformation codebase in a separate method, pass immutable props to it and have 100% of activity to happen on that thread. I tried cross-referencing variables (as you see below with transformedMessage = (...) ), I tried returning transformed message and awaiting for it from Task / Joining a thread. Lastly, I also tried for loop with a Thread.Sleep on parent thread, to see if I can manually abort that child thread after few loops.

I tried a lot, and none of my approaches work - Visual Studio always, first hangs for few minutes, then throws stack overflow exception on that xslt.Transform - I am definitely missing something here in my approach.

A long post, so here is the question: Why does a child thread with a stack overflow exception blocks parent thread from continuing being processed ? Perhaps it has something to do with.Net core/MVC and the way VS built in server handles things? Is this a bug in VS/.Net core, or I am unaware of something when it comes to parallel processing?

using (var tokenSource = new CancellationTokenSource(1000)) {
    try {
        var token = tokenSource.Token;
        var task = Task.Run(()=>{
            xslt.Transform(xri, args, xwo);
            transformedMessage = sw.ToString();
        }, token);
        await task; //don't focus on this, it's just one of many versions I have tried, debugger does not even reach this point
    } catch (TaskCanceledException) {
        throw new TimeoutException("Timeout");
    }
}

I'm not sure it helps you or not but you can try with ContinueWith on task and add another chain for handle exception, like this:

await Task.Run(()=>{
            xslt.Transform(xri, args, xwo);
            transformedMessage = sw.ToString();
        }, token)
     .ContinueWith(x=>{
             if(x.Exception!=null)
                 Console.WriteLine(x.Exception.Message);
             else Console.WriteLine("successful");
         }
        );

Stackoverflow exceptions are unrecoverable exceptions. You cannot handle it, and need to fix that issue. You can spawn new threads to avoid the stack overflow in the first place, but stackoverflows are terminal and crash the process.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM