This patch fixes two issues in the exception handling backend
(transforms actual results reported below to expected results
reported below).
Environment:
Branch: master
Emcc -v: emcc (Emscripten gcc/clang-like replacement + linker
emulating GNU ld) 1.36.0
clang version 3.9.0
(https://github.com/kripken/emscripten-fastcomp-clang/
271ce598c3d1fe74efadc254f5be1b57edea9f41)
(https://github.com/kripken/emscripten-fastcomp/
61acfb230665464544f2e8db292f8999fc3c628c)
(emscripten 1.36.0 : 1.36.0)
Target: x86_64-apple-darwin16.0.0
Thread model: posix
InstalledDir: /Users/ray/src/gm/emsdk_portable/clang/
fastcomp/build_master_64/bin
INFO:root:(Emscripten: Running sanity checks)
Issue 1: Re-thrown exceptions leak (and their destructors are
not invoked)
Repro:
#include <iostream>
struct NeedsCleanUp
{
NeedsCleanUp()
{
std::cout << "Creating cleanup item" << std::endl;
}
~NeedsCleanUp()
{
std::cout << "Destroying cleanup item" << std::endl;
}
};
int main(int argc, char* argv[])
{
try
{
try
{
throw NeedsCleanUp {};
}
catch (...)
{
throw; // rethrow causes leak
}
}
catch (...)
{
}
return 0;
}
Build and run:
em++ -g -std=c++11 --emrun -s EXCEPTION_DEBUG=0 -o exc1.html exc1.cpp
emrun --browser chrome exc1.html
ACTUAL RESULT:
pre-main prep time: 23 ms
Creating cleanup item
ACTUAL RESULT WITH EXCEPTION DEBUG:
pre-main prep time: 25 ms
Creating cleanup item
Compiled code throwing an exception, 5267520,8,357
can_catch on 5267520
cxa_begin_catch 5267520,stack,5267520
addref 5267520
Compiled code RE-throwing an exception, popped 5267520,5267520,stack,
can_catch on 5267520
cxa_begin_catch 5267520,stack,5267520
addref 5267520
cxa_end_catch popped 5267520,5267520,stack,
decref 5267520
EXPECTED RESULT:
pre-main prep time: 23 ms
Creating cleanup item
Destroying cleanup item
EXPECTED RESULT WITH EXCEPTION DEBUG:
pre-main prep time: 24 ms
Creating cleanup item
Compiled code throwing an exception, 5267520,8,357
can_catch on 5267520
cxa_begin_catch 5267520,stack,5267520
addref 5267520
Compiled code RE-throwing an exception, popped 5267520,5267520,stack,
5267520
can_catch on 5267520
cxa_end_catch popped 5267520,5267520,stack,
decref 5267520
cxa_begin_catch 5267520,stack,5267520
addref 5267520
cxa_end_catch popped 5267520,0,stack,
decref 5267520
Destroying cleanup item
decref freeing exception 5267520,0,stack,
=======================================================================
Issue 2: Resuming exception unwinding causes crash when resumed
exceptions have multiple references
Repro:
#include <iostream>
struct NeedsCleanUp
{
const int item;
NeedsCleanUp(int i)
: item { i }
{
std::cout << "Creating cleanup item " << item << std::endl;
}
NeedsCleanUp(const NeedsCleanUp& src)
: item { 100 + src.item }
{
std::cout << "Copying cleanup item " << src.item << " to "
<< item << std::endl;
}
~NeedsCleanUp()
{
std::cout << "Destroying cleanup item " << item << std::endl;
}
};
int main(int argc, char* argv[])
{
NeedsCleanUp ex { 1 };
std::exception_ptr exp1 { std::make_exception_ptr(ex) };
std::exception_ptr exp2 { exp1 };
try
{
[&exp1] {
NeedsCleanUp cl { 2 }; // causes "resuming exception"
// ref count reset
std::rethrow_exception(exp1);
} ();
}
catch (...)
{
}
return 0;
}
Build and run:
em++ -g -std=c++11 --emrun -s EXCEPTION_DEBUG=0 -o exc2.html exc2.cpp
emrun --browser chrome exc2.html
ACTUAL RESULT:
pre-main prep time: 23 ms
Creating cleanup item 1
Copying cleanup item 1 to 101
Copying cleanup item 101 to 201
Destroying cleanup item 101
Creating cleanup item 2
Destroying cleanup item 2
Destroying cleanup item 201
exception thrown: TypeError: Cannot read property 'refcount' of
undefined,TypeError: Cannot read property 'refcount' of undefined
at Object.decRef (http://localhost:6931/exc2.js:1564:20)
at ___cxa_decrement_exception_refcount
(http://localhost:6931/exc2.js:1578:18)
at __ZNSt13exception_ptrD2Ev (http://localhost:6931/exc2.js:23642:2)
at _main (http://localhost:6931/exc2.js:5993:3)
at Object.asm._main (http://localhost:6931/exc2.js:65981:19)
at Object.callMain (http://localhost:6931/exc2.js:66150:30)
at doRun (http://localhost:6931/exc2.js:66208:60)
at http://localhost:6931/exc2.js:66219:7
ACTUAL RESULT WITH EXCEPTION DEBUG:
pre-main prep time: 22 ms
Creating cleanup item 1
Copying cleanup item 1 to 101
Copying cleanup item 101 to 201
Compiled code throwing an exception, 5267520,8,360
can_catch on 5267520
cxa_begin_catch 5267520,stack,5267520
addref 5267520
addref 5267520
cxa_end_catch popped 5267520,5267520,stack,
decref 5267520
Destroying cleanup item 101
addref 5267520
Creating cleanup item 2
addref 5267520
Compiled code RE-throwing an exception, popped 5267520,0,stack,
can_catch on 5267520
decref 5267520
Destroying cleanup item 2
Resuming exception 5267520,5267520
can_catch on 5267520
cxa_begin_catch 5267520,stack,5267520
addref 5267520
decref 5267520
Destroying cleanup item 201
decref freeing exception 5267520,5267520,stack,5267520
no de-adjustment for unknown exception ptr 5267520
decref 5267520
exception thrown: TypeError: Cannot read property 'refcount' of
undefined,TypeError: Cannot read property 'refcount' of undefined
at Object.decRef (http://localhost:6931/exc2.js:1568:20)
at ___cxa_decrement_exception_refcount
(http://localhost:6931/exc2.js:1583:18)
at __ZNSt13exception_ptrD2Ev (http://localhost:6931/exc2.js:23654:2)
at _main (http://localhost:6931/exc2.js:6005:3)
at Object.asm._main (http://localhost:6931/exc2.js:65993:19)
at Object.callMain (http://localhost:6931/exc2.js:66162:30)
at doRun (http://localhost:6931/exc2.js:66220:60)
at http://localhost:6931/exc2.js:66231:7
EXPECTED RESULT:
pre-main prep time: 22 ms
Creating cleanup item 1
Copying cleanup item 1 to 101
Copying cleanup item 101 to 201
Destroying cleanup item 101
Creating cleanup item 2
Destroying cleanup item 2
Destroying cleanup item 201
Destroying cleanup item 1
EXPECTED RESULT WITH EXCEPTION DEBUG:
pre-main prep time: 27 ms
Creating cleanup item 1
Copying cleanup item 1 to 101
Copying cleanup item 101 to 201
Compiled code throwing an exception, 5267520,8,360
can_catch on 5267520
cxa_begin_catch 5267520,stack,5267520
addref 5267520
addref 5267520
cxa_end_catch popped 5267520,5267520,stack,
decref 5267520
Destroying cleanup item 101
addref 5267520
Creating cleanup item 2
addref 5267520
Compiled code RE-throwing an exception, popped 5267520,0,stack,5267520
can_catch on 5267520
decref 5267520
Destroying cleanup item 2
Resuming exception 5267520,5267520
can_catch on 5267520
cxa_begin_catch 5267520,stack,5267520,5267520
addref 5267520
cxa_end_catch popped 5267520,5267520,stack,5267520
decref 5267520
decref 5267520
decref 5267520
Destroying cleanup item 201
decref freeing exception 5267520,0,stack,5267520
Destroying cleanup item 1