Hello,
we are having issues with a portion of code that basically provokes an exception in user code called by clearscript, and then calls Interrupt on the V8 engine.
It always crashes. Isn't this scenario supposed to function properly ? (I mean, Interrupt should not crash... ?)
Should I explicitely wait before Interrupting in this case ? (but this would be some sort of workaround?)
Cdlt,
Julien.
btw: reproduced on ClearScript 5.4.6 (Nuget version)
```
[Test]
public virtual void TestScriptTerminateCrash()
{
var ctx = new PropertyBag();
using (var engine = new V8ScriptEngine("CrashScript"))
{
engine.AddHostObject("context", ctx);
var eventW = new ManualResetEventSlim(initialState: false);
var tokenSource = new CancellationTokenSource();
// start notification only
var startEvent = new ManualResetEventSlim(false);
ThreadStart main = () =>
{
try
{
ctx["waitCode"] = new Action(() =>
{
// Waiting in the C# code : a cancel exception is generated here
eventW.Wait(tokenSource.Token);
});
ctx["startEvent"] = startEvent;
ctx["counter"] = 0;
try
{
System.DateTime dtRun = System.DateTime.UtcNow;
engine.Execute("dummyDocument.js", @"
// Start
context.counter = 1;
context.startEvent.Set();
context.counter = 2;
context.waitCode();
context.counter = 3;
");
Assert.Inconclusive();
}
catch (Microsoft.ClearScript.ScriptInterruptedException si)
{
Assert.That(si.Message.Contains("interrupted"));
}
catch (Microsoft.ClearScript.ScriptEngineException segx)
{
if (segx.InnerException is System.Reflection.TargetInvocationException &&
segx.InnerException.InnerException != null)
throw segx.InnerException.InnerException;
Assert.Fail();
}
}
catch (OperationCanceledException)
{
}
catch (Exception)
{
Assert.Fail();
}
};
var t = new Thread(main);
t.Start();
Assert.That(startEvent.Wait(5000));
// Cancel + interrupt
tokenSource.Cancel();
//Thread.Sleep(1000); // won't fail if we interrupt later
engine.Interrupt();
t.Join();
Assert.AreEqual(2, (Int32)ctx["counter"]);
}
}
```
Comments: Actually, our upcoming change avoids throwing exceptions when script interruption is in progress. Because JavaScript object allocation fails when V8 is in that state, the JavaScript wrapper for the managed exception cannot be constructed. The fix eliminates the crash and should provide consistent behavior in this scenario.
we are having issues with a portion of code that basically provokes an exception in user code called by clearscript, and then calls Interrupt on the V8 engine.
It always crashes. Isn't this scenario supposed to function properly ? (I mean, Interrupt should not crash... ?)
Should I explicitely wait before Interrupting in this case ? (but this would be some sort of workaround?)
Cdlt,
Julien.
btw: reproduced on ClearScript 5.4.6 (Nuget version)
```
[Test]
public virtual void TestScriptTerminateCrash()
{
var ctx = new PropertyBag();
using (var engine = new V8ScriptEngine("CrashScript"))
{
engine.AddHostObject("context", ctx);
var eventW = new ManualResetEventSlim(initialState: false);
var tokenSource = new CancellationTokenSource();
// start notification only
var startEvent = new ManualResetEventSlim(false);
ThreadStart main = () =>
{
try
{
ctx["waitCode"] = new Action(() =>
{
// Waiting in the C# code : a cancel exception is generated here
eventW.Wait(tokenSource.Token);
});
ctx["startEvent"] = startEvent;
ctx["counter"] = 0;
try
{
System.DateTime dtRun = System.DateTime.UtcNow;
engine.Execute("dummyDocument.js", @"
// Start
context.counter = 1;
context.startEvent.Set();
context.counter = 2;
context.waitCode();
context.counter = 3;
");
Assert.Inconclusive();
}
catch (Microsoft.ClearScript.ScriptInterruptedException si)
{
Assert.That(si.Message.Contains("interrupted"));
}
catch (Microsoft.ClearScript.ScriptEngineException segx)
{
if (segx.InnerException is System.Reflection.TargetInvocationException &&
segx.InnerException.InnerException != null)
throw segx.InnerException.InnerException;
Assert.Fail();
}
}
catch (OperationCanceledException)
{
}
catch (Exception)
{
Assert.Fail();
}
};
var t = new Thread(main);
t.Start();
Assert.That(startEvent.Wait(5000));
// Cancel + interrupt
tokenSource.Cancel();
//Thread.Sleep(1000); // won't fail if we interrupt later
engine.Interrupt();
t.Join();
Assert.AreEqual(2, (Int32)ctx["counter"]);
}
}
```
Comments: Actually, our upcoming change avoids throwing exceptions when script interruption is in progress. Because JavaScript object allocation fails when V8 is in that state, the JavaScript wrapper for the managed exception cannot be constructed. The fix eliminates the crash and should provide consistent behavior in this scenario.