Potential Stackoverflow on Azure Web Apps

Feb 2, 2016 at 2:12 PM
We're using ClearScript.v8 (via React.NET) in asp.net web apps hosted in Azure and we get intermittent seemingly random occurrences of "Unknown error; potential stack overflow detected" which is coming from within the Clearscript.V8 code. Does anyone have any insight into the conditions that cause this - it seems to be very random and renders an engine unusable (the engine will have been taken from a runtime and executed scripts only a handful of times, after the error every attempt to execute code by that instance gets this error). I've played with the way the Runtime and Engines get used e.g. the number of usages of each instance, and also tried frequent garbage collection but to no avail.
It feels as if it's something environmental - a memory or other condition that makes the underlying V8 instance behave in a way that in turn triggers the error in ClearScript.V8.
NB We're running 32-bit but feel that while running 64-bit could alleviate the issue, it won't eliminate it unless someone can advise otherwise.
Feb 2, 2016 at 3:43 PM

The error message you're seeing indicates the following:
  1. Script execution ended prematurely due to an uncaught script exception.
  2. Converting the thrown object to a string yielded an empty string.
Because of (2), no error message is available; hence "Unknown error". Additionally, in our own testing, we've observed V8 throwing such an object only during stack overflow recovery; hence "potential stack overflow detected".

However, more recently we found that simply throwing an empty string (or any object whose toString method returns an empty string) produces the same result. That's a ClearScript bug we need to fix, at least to enable stack traces in such situations.

In the meantime, is it possible that your script throws such an object? Consider adding a try..catch block to detect that. If not, you may actually be hitting a stack overflow. Are you specifying stack usage limits for your V8 runtimes?

Good luck!
Feb 3, 2016 at 11:03 AM

Thanks for the prompt reply. We used to get the error occurring in various execution paths but after upgrades and refinements (such as tuning the reuse of runtimes and engines, invoking garbage collection, precompiling scripts) it has narrowed down to one scenario/piece of code:
(typeof _myVariable !== 'undefined')
This will have been run before every execution of javascript code across all our requests hence the fact that it's seemingly random given it only happens once in a while. We could indeed try...catch and retry or even dispose the engine and initialise a new one but only want to do that as a last resort (e.g. if that's the nature of the v8 engine). Other options could be to change the above code if it's causing the condition within v8... but it all seems very odd as we've only ever seen it on azure apart from when i artificially created it by setting the stack usage limit to a low figure - otherwise we don't set stack usage limits.

Thanks once again.
Feb 3, 2016 at 4:13 PM
Hi James,

Interesting. Are you saying that the JavaScript expression above is somehow responsible for the issues you're seeing?

In any case, try..catch might be a low-cost way to diagnose the problem. It won't catch true stack overflows, but it should be able to find cases of empty strings (or similar objects) being thrown, and it shouldn't affect your application's performance.

Consider also that true stack overflows aren't uncommon. ClearScript can build up large stacks, especially with nested script execution, and the default stack allocation is typically only 1 MB.

Feb 9, 2016 at 10:44 AM
A quick related question - what happens if I dispose a V8Runtime instance then still try to use a V8Engine instance that was created from that runtime (then dispose it)?
Could this scenario cause the potential stackoverflow?
Feb 9, 2016 at 1:55 PM
Hi James,

This scenario should be fine; that is, it shouldn't cause any issues. An active V8ScriptEngine maintains a strong reference to its associated (unmanaged) V8 runtime. Note that a script object only holds a weak reference to its unmanaged counterpart, so disposing its parent engine or runtime turns it into a "zombie".

Good luck!
Feb 9, 2016 at 2:20 PM
Many many thanks - I checked and i wasn't disposing of the compiled script objects that each Runtime had compiled so am now explicitly disposing of them :)
So if the last V8Engine spawned from a managed runtime is disposed after the managed runtime has already been disposed, will the unmanaged runtime instance be destroyed/deallocated?

Feb 9, 2016 at 5:27 PM
So if the last V8Engine spawned from a managed runtime is disposed after the managed runtime has already been disposed, will the unmanaged runtime instance be destroyed/deallocated?

Yes, it should. The managed engine and runtime are proxies for reference-counted unmanaged objects. Disposing or finalizing a proxy decrements its target's reference count, and the target is destroyed when its reference count reaches zero. Furthermore, the unmanaged engine holds an additional reference to its parent runtime, so the runtime will be kept alive as long as the engine remains active, regardless of whether a runtime proxy exists on the managed side.

Feb 24, 2016 at 3:09 PM
Hi there
Thanks for that insight - that should mean that even under high load where we will spawn additional runtimes and engines we shouldn't have any zombie instances left lying around after disposing of all of them. Have tracked down further potential problematic usages of the runtime (finding a global variable that mocked the console and getting all the calls made to it) and waiting to see if the errors resurface - so far we haven't done a try...catch. Fingers crossed that's it. Cheers for your help so far.