aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlon Zakai <alonzakai@gmail.com>2013-01-07 12:54:29 -0800
committerAlon Zakai <alonzakai@gmail.com>2013-01-07 12:54:29 -0800
commit578971453d4d1140486229bedc711f52b8e1948f (patch)
tree72f2371905d7d08a1a86641ccd977649088dcde9
parent904d9b751241bfa1e1a334877c8489a27e535892 (diff)
reset the stack top when CATCH_EXIT_CODE
-rw-r--r--src/postamble.js4
-rw-r--r--src/settings.js4
-rwxr-xr-xtests/runner.py47
3 files changed, 54 insertions, 1 deletions
diff --git a/src/postamble.js b/src/postamble.js
index 83a4daa6..5f541733 100644
--- a/src/postamble.js
+++ b/src/postamble.js
@@ -18,10 +18,14 @@ Module.callMain = function callMain(args) {
argv = allocate(argv, 'i32', ALLOC_STATIC);
#if CATCH_EXIT_CODE
+ var initialStackTop = STACKTOP;
try {
return Module['_main'](argc, argv, 0);
}
catch(e) { if (e.name == "ExitStatus") return e.status; throw e; }
+ finally {
+ STACKTOP = initialStackTop;
+ }
#else
return Module['_main'](argc, argv, 0);
#endif
diff --git a/src/settings.js b/src/settings.js
index 84d64167..11af4692 100644
--- a/src/settings.js
+++ b/src/settings.js
@@ -118,7 +118,9 @@ var INLINING_LIMIT = 50; // A limit on inlining. If 0, we will inline normally i
var CATCH_EXIT_CODE = 0; // If set, causes exit() to throw an exception object which is caught
// in a try..catch block and results in the exit status being
// returned from run(). If zero (the default), the program is just
- // terminated with an error message.
+ // terminated with an error message, that is, the exception thrown
+ // by exit() is not handled in any way (in particular, the stack
+ // position will not be reset).
// Generated code debugging options
var SAFE_HEAP = 0; // Check each write to the heap, for example, this will give a clear
diff --git a/tests/runner.py b/tests/runner.py
index e55a3f60..742ddf1f 100755
--- a/tests/runner.py
+++ b/tests/runner.py
@@ -2471,6 +2471,53 @@ setjmp exception execution path, level: 0, prev_jmp: -1
Exiting setjmp function, level: 0, prev_jmp: -1
''')
+ def test_exit_stack(self):
+ if self.emcc_args is None: return self.skip('requires emcc')
+ if Settings.ASM_JS: return self.skip('uses report_stack without exporting')
+
+ Settings.CATCH_EXIT_CODE = 1
+
+ src = r'''
+ #include <stdio.h>
+ #include <stdlib.h>
+
+ extern "C" {
+ extern void report_stack(int x);
+ }
+
+ char moar() {
+ char temp[125];
+ for (int i = 0; i < 125; i++) temp[i] = i*i;
+ for (int i = 1; i < 125; i++) temp[i] += temp[i-1]/2;
+ if (temp[100] != 99) exit(1);
+ return temp[120];
+ }
+
+ int main(int argc, char *argv[]) {
+ report_stack((int)alloca(4));
+ printf("*%d*\n", moar());
+ return 0;
+ }
+ '''
+
+ open(os.path.join(self.get_dir(), 'pre.js'), 'w').write('''
+ var initialStack = -1;
+ var _report_stack = function(x) {
+ Module.print('reported');
+ initialStack = x;
+ }
+ var Module = {
+ postRun: function() {
+ Module.print('postRun');
+ assert(initialStack == STACKTOP, [initialStack, STACKTOP]);
+ Module.print('ok.');
+ }
+ };
+ ''')
+
+ self.emcc_args += ['--pre-js', 'pre.js']
+ self.do_run(src, '''reported\npostRun\nok.\nExit Status: 1\n''')
+
def test_class(self):
src = '''
#include <stdio.h>