diff options
author | Kent Hansen <kent.hansen@nokia.com> | 2012-08-20 12:40:36 +0200 |
---|---|---|
committer | Qt by Nokia <qt-info@nokia.com> | 2012-08-22 09:11:30 +0200 |
commit | 9429a85a2160cf8b860b1292e4e0bc0855841755 (patch) | |
tree | b255ba0f8f5e895fcc3c3cd90fd31d7ca391a143 /src/script/api/qscriptengine.cpp | |
parent | 75c649276a9bbcb2e593d6c6f78d77417dd05891 (diff) | |
download | qtscript-9429a85a2160cf8b860b1292e4e0bc0855841755.tar.gz |
Capture full backtrace when a native function calls back into JS
Commit df0ec196031d33850324dc5eeed2d71f61413885 assumed that JSC's
Interpreter::throwException function is called exactly once when an
exception occurs. That's wrong. If there is a native call inbetween
two JS calls on the stack, the call stack will be unwound to the
point of the native call frame, and throwException will return. After
the native (C) call frame has been unwound, throwException will be
called again to unwind remaining JS call frames, and so on.
This was causing QtScript to discard the backtrace belonging to the
inner-most JS frames; the backtrace would be regenerated from a
partially unwound state.
Fix this by ignoring subsequent calls to the uncaughtException()
callback once a backtrace has been captured; the backtrace is already
cleared before each evaluation is started.
Task-number: QTBUG-26889
Change-Id: I03e1d60fbac5e592cff1dd5ef70f397cf94454ae
Reviewed-by: Simon Hausmann <simon.hausmann@nokia.com>
Diffstat (limited to 'src/script/api/qscriptengine.cpp')
-rw-r--r-- | src/script/api/qscriptengine.cpp | 12 |
1 files changed, 10 insertions, 2 deletions
diff --git a/src/script/api/qscriptengine.cpp b/src/script/api/qscriptengine.cpp index d96d11c..8186dec 100644 --- a/src/script/api/qscriptengine.cpp +++ b/src/script/api/qscriptengine.cpp @@ -1434,12 +1434,20 @@ bool QScriptEnginePrivate::isLikelyStackOverflowError(JSC::ExecState *exec, JSC: /*! \internal - Called by the VM when an uncaught exception is detected. - At the time of this call, the VM stack has not yet been unwound. + Called by the VM when an uncaught exception is being processed. + If the VM call stack contains a native call inbetween two JS calls at the + time the exception is thrown, this function will get called multiple times + for a single exception (once per "interval" of JS call frames). In other + words, at the time of this call, the VM stack can be in a partially unwound + state. */ void QScriptEnginePrivate::uncaughtException(JSC::ExecState *exec, unsigned bytecodeOffset, JSC::JSValue value) { + // Don't capture exception information if we already have. + if (uncaughtExceptionLineNumber != -1) + return; + QScript::SaveFrameHelper saveFrame(this, exec); uncaughtExceptionLineNumber = exec->codeBlock()->lineNumberForBytecodeOffset(exec, bytecodeOffset); |