- always throw an exception in exit

- remove default exit status prints
 - added EXITSTATUS global to enable exit callbacks to determine the status
This commit is contained in:
Anthony Pesch 2013-08-09 00:36:35 -07:00
Родитель bd1d02e02c
Коммит a9bb2f0261
3 изменённых файлов: 57 добавлений и 34 удалений

Просмотреть файл

@ -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);
}

Просмотреть файл

@ -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

Просмотреть файл

@ -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):