- 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:
Родитель
bd1d02e02c
Коммит
a9bb2f0261
|
@ -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):
|
||||
|
|
Загрузка…
Ссылка в новой задаче