aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnthony Pesch <inolen@gmail.com>2013-08-09 00:36:35 -0700
committerAnthony Pesch <inolen@gmail.com>2013-08-09 11:11:12 -0700
commita9bb2f0261fd88048d7e499df33808a23884cb02 (patch)
tree9fd6f9aebf7ca97f8220d914b2eecc20501f56f9
parentbd1d02e02cf0f39c8d7f672520910714d1c2d4e5 (diff)
- always throw an exception in exit
- remove default exit status prints - added EXITSTATUS global to enable exit callbacks to determine the status
-rw-r--r--src/postamble.js60
-rw-r--r--src/preamble.js1
-rwxr-xr-xtests/runner.py30
3 files changed, 57 insertions, 34 deletions
diff --git a/src/postamble.js b/src/postamble.js
index 25a50bfc..ad265b32 100644
--- a/src/postamble.js
+++ b/src/postamble.js
@@ -2,7 +2,6 @@
// === Auto-generated postamble setup entry stuff ===
var initialStackTop;
-var inMain;
Module['callMain'] = Module.callMain = function callMain(args) {
assert(runDependencies == 0, 'cannot call main when async dependencies remain! (listen on __ATMAIN__)');
@@ -27,40 +26,36 @@ Module['callMain'] = Module.callMain = function callMain(args) {
argv.push(0);
argv = allocate(argv, 'i32', ALLOC_NORMAL);
+ initialStackTop = STACKTOP;
+
+ try {
#if BENCHMARK
- var start = Date.now();
+ var start = Date.now();
#endif
- initialStackTop = STACKTOP;
- inMain = true;
+ var ret = Module['_main'](argc, argv, 0);
- var ret;
- try {
- ret = Module['_main'](argc, argv, 0);
+#if BENCHMARK
+ Module.realPrint('main() took ' + (Date.now() - start) + ' milliseconds');
+#endif
+
+ // if we're not running an evented main loop, it's time to exit
+ if (!Module['noExitRuntime']) {
+ exit(ret);
+ }
}
catch(e) {
- if (e && typeof e == 'object' && e.type == 'ExitStatus') {
+ if (e.name == 'ExitStatus') {
// exit() throws this once it's done to make sure execution
// has been stopped completely
- Module.print('Exit Status: ' + e.value);
- return e.value;
+ return;
} else if (e == 'SimulateInfiniteLoop') {
// running an evented main loop, don't immediately exit
Module['noExitRuntime'] = true;
+ return;
} else {
throw e;
}
- } finally {
- inMain = false;
- }
-
-#if BENCHMARK
- Module.realPrint('main() took ' + (Date.now() - start) + ' milliseconds');
-#endif
-
- // if we're not running an evented main loop, it's time to exit
- if (!Module['noExitRuntime']) {
- exit(ret);
}
}
@@ -110,21 +105,21 @@ Module['run'] = Module.run = run;
function exit(status) {
ABORT = true;
+ EXITSTATUS = status;
STACKTOP = initialStackTop;
- // TODO call externally added 'exit' callbacks with the status code.
- // It'd be nice to provide the same interface for all Module events (e.g.
- // prerun, premain, postmain). Perhaps an EventEmitter so we can do:
- // Module.on('exit', function (status) {});
-
// exit the runtime
exitRuntime();
-
- if (inMain) {
- // if we're still inside the callMain's try/catch, we need to throw an
- // exception in order to immediately terminate execution.
- throw { type: 'ExitStatus', value: status };
- }
+
+ // throw an exception to halt the current execution
+ function ExitStatus() {
+ this.name = "ExitStatus";
+ this.message = "Program terminated with exit(" + status + ")";
+ this.status = status;
+ };
+ ExitStatus.prototype = new Error();
+ ExitStatus.prototype.constructor = ExitStatus;
+ throw new ExitStatus();
}
Module['exit'] = Module.exit = exit;
@@ -134,6 +129,7 @@ function abort(text) {
}
ABORT = true;
+ EXITSTATUS = 1;
throw 'abort() at ' + (new Error().stack);
}
diff --git a/src/preamble.js b/src/preamble.js
index 585db832..95bf2dc2 100644
--- a/src/preamble.js
+++ b/src/preamble.js
@@ -241,6 +241,7 @@ var setjmpLabels = {};
#endif
var ABORT = false; // whether we are quitting the application. no code should run after this. set in exit() and abort()
+var EXITSTATUS = 0;
var undef = 0;
// tempInt is used for 32-bit signed values or smaller. tempBigInt is used
diff --git a/tests/runner.py b/tests/runner.py
index e77efffb..8122bc81 100755
--- a/tests/runner.py
+++ b/tests/runner.py
@@ -3185,6 +3185,25 @@ Exiting setjmp function, level: 0, prev_jmp: -1
'''
self.do_run(src, 'caught std::exception')
+ def test_async_exit(self):
+ open('main.c', 'w').write(r'''
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include "emscripten.h"
+
+ void main_loop() {
+ exit(EXIT_SUCCESS);
+ }
+
+ int main() {
+ emscripten_set_main_loop(main_loop, 60, 0);
+ return 0;
+ }
+ ''')
+
+ Popen([PYTHON, EMCC, 'main.c']).communicate()
+ self.assertNotContained('Reached an unreachable!', run_js(self.in_dir('a.out.js'), stderr=STDOUT))
+
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')
@@ -3222,6 +3241,7 @@ Exiting setjmp function, level: 0, prev_jmp: -1
}
var Module = {
postRun: function() {
+ Module.print('Exit Status: ' + EXITSTATUS);
Module.print('postRun');
assert(initialStack == STACKTOP, [initialStack, STACKTOP]);
Module.print('ok.');
@@ -10219,13 +10239,19 @@ def process(filename):
printf("cleanup\n");
}
- int main()
- {
+ int main() {
atexit(cleanup); // this atexit should still be called
printf("hello, world!\n");
exit(118); // Unusual exit status to make sure it's working!
}
'''
+ open('post.js', 'w').write('''
+ Module.addOnExit(function () {
+ Module.print('Exit Status: ' + EXITSTATUS);
+ });
+ Module.callMain();
+ ''')
+ self.emcc_args += ['-s', 'INVOKE_RUN=0', '--post-js', 'post.js']
self.do_run(src, 'hello, world!\ncleanup\nExit Status: 118')
def test_gc(self):