Skip to content

Commit d3666c0

Browse files
committed
Deprecate DISABLE_EXCEPTION_CATCHING=2
We can instead imply this mode by the presence of the EXCEPTION_CATCHING_ALLOWED` list. This turns DISABLE_EXCEPTION_CATCHING into a binary option which is easier to deal with both internally and externally.
1 parent 2654899 commit d3666c0

File tree

7 files changed

+71
-31
lines changed

7 files changed

+71
-31
lines changed

ChangeLog.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,11 @@ Current Trunk
2222
-------------
2323
- Values returned from `sysconf` now more closely match the definitions found in
2424
header files and in upstream musl (#13713).
25+
- `DISABLE_EXCEPTION_CATCHING=2` is now deprecated since it can be inferred from
26+
the presence of the `EXCEPTION_CATCHING_ALLOWED` list. This makes
27+
`DISABLE_EXCEPTION_CATCHING` a simple binary option (0 or 1) which defaults to
28+
0 which will be set to 1 internally if `EXCEPTION_CATCHING_ALLOWED` list is
29+
specified.
2530
- Values returned from `pathconf` now match the definitions found in header files
2631
and/or upstream musl:
2732
_PC_LINK_MAX 3200 -> 8

emcc.py

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -751,7 +751,7 @@ def get_cflags(options, user_args):
751751

752752
# if exception catching is disabled, we can prevent that code from being
753753
# generated in the frontend
754-
if shared.Settings.DISABLE_EXCEPTION_CATCHING == 1 and not shared.Settings.EXCEPTION_HANDLING:
754+
if shared.Settings.DISABLE_EXCEPTION_CATCHING and not shared.Settings.EXCEPTION_HANDLING:
755755
cflags.append('-fignore-exceptions')
756756

757757
if shared.Settings.INLINING_LIMIT:
@@ -1588,6 +1588,18 @@ def default_setting(name, new_default):
15881588
default_setting('ERROR_ON_UNDEFINED_SYMBOLS', 0)
15891589
default_setting('WARN_ON_UNDEFINED_SYMBOLS', 0)
15901590

1591+
if 'DISABLE_EXCEPTION_CATCHING' in settings_key_changes and 'EXCEPTION_CATCHING_ALLOWED' in settings_key_changes:
1592+
# If we get here then the user specified both DISABLE_EXCEPTION_CATCHING and EXCEPTION_CATCHING_ALLOWED
1593+
# on the command line. This is no longer valid so report either an error or a warning (for
1594+
# backwards compat with the old `DISABLE_EXCEPTION_CATCHING=2`
1595+
if settings_key_changes['DISABLE_EXCEPTION_CATCHING'] in ('0', '2'):
1596+
diagnostics.warning('deprecated', 'DISABLE_EXCEPTION_CATCHING=X is no longer needed when specifying EXCEPTION_CATCHING_ALLOWED')
1597+
else:
1598+
exit_with_error('DISABLE_EXCEPTION_CATCHING and EXCEPTION_CATCHING_ALLOWED are mutually exclusive')
1599+
1600+
if shared.Settings.EXCEPTION_CATCHING_ALLOWED:
1601+
shared.Settings.DISABLE_EXCEPTION_CATCHING = 0
1602+
15911603
if shared.Settings.DISABLE_EXCEPTION_THROWING and not shared.Settings.DISABLE_EXCEPTION_CATCHING:
15921604
exit_with_error("DISABLE_EXCEPTION_THROWING was set (probably from -fno-exceptions) but is not compatible with enabling exception catching (DISABLE_EXCEPTION_CATCHING=0). If you don't want exceptions, set DISABLE_EXCEPTION_CATCHING to 1; if you do want exceptions, don't link with -fno-exceptions")
15931605

@@ -1640,7 +1652,7 @@ def default_setting(name, new_default):
16401652

16411653
if shared.Settings.USE_PTHREADS:
16421654
if shared.Settings.USE_PTHREADS == 2:
1643-
exit_with_error('USE_PTHREADS=2 is not longer supported')
1655+
exit_with_error('USE_PTHREADS=2 is no longer supported')
16441656
if shared.Settings.ALLOW_MEMORY_GROWTH:
16451657
diagnostics.warning('pthreads-mem-growth', 'USE_PTHREADS + ALLOW_MEMORY_GROWTH may run non-wasm code slowly, see https://github.com/WebAssembly/design/issues/1271')
16461658
# UTF8Decoder.decode may not work with a view of a SharedArrayBuffer, see https://github.com/whatwg/encoding/issues/172
@@ -1965,7 +1977,7 @@ def check_memory_setting(setting):
19651977
shared.Settings.USE_PTHREADS or \
19661978
shared.Settings.OFFSCREENCANVAS_SUPPORT or \
19671979
shared.Settings.LEGACY_GL_EMULATION or \
1968-
shared.Settings.DISABLE_EXCEPTION_CATCHING != 1 or \
1980+
not shared.Settings.DISABLE_EXCEPTION_CATCHING or \
19691981
shared.Settings.ASYNCIFY or \
19701982
shared.Settings.ASMFS or \
19711983
shared.Settings.DEMANGLE_SUPPORT or \
@@ -1978,7 +1990,7 @@ def check_memory_setting(setting):
19781990
sanitize:
19791991
shared.Settings.EXPORTED_FUNCTIONS += ['_malloc', '_free']
19801992

1981-
if shared.Settings.DISABLE_EXCEPTION_CATCHING != 1:
1993+
if not shared.Settings.DISABLE_EXCEPTION_CATCHING:
19821994
# If not for LTO builds, we could handle these by adding deps_info.py
19831995
# entries for __cxa_find_matching_catch_* functions. However, under
19841996
# LTO these symbols don't exist prior the linking.

src/parseTools.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -873,8 +873,8 @@ function makeStructuralReturn(values) {
873873
}
874874

875875
function makeThrow(what) {
876-
if (ASSERTIONS && DISABLE_EXCEPTION_CATCHING == 1) {
877-
what += ' + " - Exception catching is disabled, this exception cannot be caught. Compile with -s DISABLE_EXCEPTION_CATCHING=0 or DISABLE_EXCEPTION_CATCHING=2 to catch."';
876+
if (ASSERTIONS && DISABLE_EXCEPTION_CATCHING) {
877+
what += ' + " - Exception catching is disabled, this exception cannot be caught. Compile with -s NO_DISABLE_EXCEPTION_CATCHING or -s EXCEPTION_CATCHING_ALLOWED=[..] to catch."';
878878
if (MAIN_MODULE) {
879879
what += ' + " (note: in dynamic linking, if a side module wants exceptions, the main module must be built with that support)"';
880880
}

src/preamble.js

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -658,11 +658,12 @@ function createExportWrapper(name, fixedasm) {
658658
#endif
659659

660660
#if ABORT_ON_WASM_EXCEPTIONS
661-
// When DISABLE_EXCEPTION_CATCHING != 1 `abortWrapperDepth` counts the recursion
662-
// level of the wrapper function so that we only handle exceptions at the top level
663-
// letting the exception mechanics work uninterrupted at the inner level.
664-
// Additionally, `abortWrapperDepth` is also manually incremented in callMain so that
665-
// we know to ignore exceptions from there since they're handled by callMain directly.
661+
// When exception catching is enabled (!DISABLE_EXCEPTION_CATCHING)
662+
// `abortWrapperDepth` counts the recursion level of the wrapper function so
663+
// that we only handle exceptions at the top level letting the exception
664+
// mechanics work uninterrupted at the inner level. Additionally,
665+
// `abortWrapperDepth` is also manually incremented in callMain so that we know
666+
// to ignore exceptions from there since they're handled by callMain directly.
666667
var abortWrapperDepth = 0;
667668

668669
// Creates a wrapper in a closure so that each wrapper gets it's own copy of 'original'
@@ -673,7 +674,7 @@ function makeAbortWrapper(original) {
673674
throw "program has already aborted!";
674675
}
675676

676-
#if DISABLE_EXCEPTION_CATCHING != 1
677+
#if !DISABLE_EXCEPTION_CATCHING
677678
abortWrapperDepth += 1;
678679
#endif
679680
try {
@@ -692,7 +693,7 @@ function makeAbortWrapper(original) {
692693

693694
abort("unhandled exception: " + [e, e.stack]);
694695
}
695-
#if DISABLE_EXCEPTION_CATCHING != 1
696+
#if !DISABLE_EXCEPTION_CATCHING
696697
finally {
697698
abortWrapperDepth -= 1;
698699
}

src/settings.js

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -643,22 +643,23 @@ var LZ4 = 0;
643643
// currently (in the future, wasm should improve that). When exceptions are
644644
// disabled, if an exception actually happens then it will not be caught
645645
// and the program will halt (so this will not introduce silent failures).
646-
// There are 3 specific modes here:
647-
// DISABLE_EXCEPTION_CATCHING = 0 - generate code to actually catch exceptions
648-
// DISABLE_EXCEPTION_CATCHING = 1 - disable exception catching at all
649-
// DISABLE_EXCEPTION_CATCHING = 2 - disable exception catching, but enables
650-
// catching in list of allowed functions
646+
//
651647
// XXX note that this removes *catching* of exceptions, which is the main
652648
// issue for speed, but you should build source files with
653649
// -fno-exceptions to really get rid of all exceptions code overhead,
654650
// as it may contain thrown exceptions that are never caught (e.g.
655651
// just using std::vector can have that). -fno-rtti may help as well.
656652
//
653+
// This option is mutually exclusive with EXCEPTION_CATCHING_ALLOWED.
654+
//
657655
// [compile+link] - affects user code at compile and system libraries at link
658656
var DISABLE_EXCEPTION_CATCHING = 1;
659657

660-
// Enables catching exception in the listed functions only, if
661-
// DISABLE_EXCEPTION_CATCHING = 2 is set
658+
// Enables catching exception but only in the listed functions. This
659+
// option acts like a more precise version of `DISABLE_EXCEPTION_CATCHING=0`.
660+
//
661+
// This option is mutually exclusive with DISABLE_EXCEPTION_CATCHING.
662+
//
662663
// [compile+link] - affects user code at compile and system libraries at link
663664
var EXCEPTION_CATCHING_ALLOWED = [];
664665

tests/test_core.py

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1236,7 +1236,6 @@ def test_exceptions_3(self):
12361236
self.do_run('src.js', 'Caught exception: Hello\nDone.', args=['2'], no_build=True)
12371237

12381238
def test_exceptions_allowed(self):
1239-
self.set_setting('DISABLE_EXCEPTION_CATCHING', 2)
12401239
# Wasm does not add an underscore to function names. For wasm, the
12411240
# mismatches are fixed in fixImports() function in JS glue code.
12421241
self.set_setting('EXCEPTION_CATCHING_ALLOWED', ["_Z12somefunctionv"])
@@ -1267,7 +1266,7 @@ def test_exceptions_allowed(self):
12671266
fake_size += os.path.getsize('test_exceptions_allowed.wasm')
12681267
shutil.copyfile('test_exceptions_allowed.js', 'fake.js')
12691268

1270-
self.set_setting('DISABLE_EXCEPTION_CATCHING')
1269+
self.clear_setting('EXCEPTION_CATCHING_ALLOWED')
12711270
self.do_run_from_file(src, empty_output, assert_returncode=NON_ZERO)
12721271
disabled_size = os.path.getsize('test_exceptions_allowed.js')
12731272
if self.is_wasm():
@@ -1278,33 +1277,55 @@ def test_exceptions_allowed(self):
12781277
print('empty_size: %d' % empty_size)
12791278
print('fake_size: %d' % fake_size)
12801279
print('disabled_size: %d' % disabled_size)
1281-
self.assertEqual(empty_size, fake_size)
1280+
# empty list acts the same as fully disabled
1281+
self.assertEqual(empty_size, disabled_size)
12821282
# big change when we disable exception catching of the function
12831283
self.assertGreater(size - empty_size, 0.01 * size)
12841284
# full disable can remove a little bit more
1285-
self.assertLess(disabled_size, empty_size)
1285+
self.assertLess(disabled_size, fake_size)
12861286

12871287
def test_exceptions_allowed_2(self):
1288-
self.set_setting('DISABLE_EXCEPTION_CATCHING', 2)
12891288
# Wasm does not add an underscore to function names. For wasm, the
12901289
# mismatches are fixed in fixImports() function in JS glue code.
1291-
self.set_setting('EXCEPTION_CATCHING_ALLOWED', ["main"])
1290+
self.set_setting('EXCEPTION_CATCHING_ALLOWED', ['main'])
12921291
# otherwise it is inlined and not identified
12931292
self.set_setting('INLINING_LIMIT')
12941293

12951294
self.do_core_test('test_exceptions_allowed_2.cpp')
12961295

12971296
def test_exceptions_allowed_uncaught(self):
12981297
self.emcc_args += ['-std=c++11']
1299-
self.set_setting('DISABLE_EXCEPTION_CATCHING', 2)
13001298
# Wasm does not add an underscore to function names. For wasm, the
13011299
# mismatches are fixed in fixImports() function in JS glue code.
1302-
self.set_setting('EXCEPTION_CATCHING_ALLOWED', ["_Z4testv"])
1300+
self.set_setting('EXCEPTION_CATCHING_ALLOWED', ['_Z4testv'])
13031301
# otherwise it is inlined and not identified
13041302
self.set_setting('INLINING_LIMIT')
13051303

13061304
self.do_core_test('test_exceptions_allowed_uncaught.cpp')
13071305

1306+
def test_exceptions_allowed_misuse(self):
1307+
self.set_setting('EXCEPTION_CATCHING_ALLOWED', ['foo'])
1308+
1309+
# Test old =2 setting for DISABLE_EXCEPTION_CATCHING
1310+
self.set_setting('DISABLE_EXCEPTION_CATCHING', 2)
1311+
err = self.expect_fail([EMCC, test_file('hello_world.c')] + self.get_emcc_args())
1312+
self.assertContained('error: DISABLE_EXCEPTION_CATCHING=X is no longer needed when specifying EXCEPTION_CATCHING_ALLOWED [-Wdeprecated] [-Werror]', err)
1313+
1314+
# =0 should also be a warning
1315+
self.set_setting('DISABLE_EXCEPTION_CATCHING', 0)
1316+
err = self.expect_fail([EMCC, test_file('hello_world.c')] + self.get_emcc_args())
1317+
self.assertContained('error: DISABLE_EXCEPTION_CATCHING=X is no longer needed when specifying EXCEPTION_CATCHING_ALLOWED [-Wdeprecated] [-Werror]', err)
1318+
1319+
# =1 should be a hard error
1320+
self.set_setting('DISABLE_EXCEPTION_CATCHING', 1)
1321+
err = self.expect_fail([EMCC, test_file('hello_world.c')] + self.get_emcc_args())
1322+
self.assertContained('error: DISABLE_EXCEPTION_CATCHING and EXCEPTION_CATCHING_ALLOWED are mutually exclusive', err)
1323+
1324+
# even setting an empty list should trigger the error;
1325+
self.set_setting('EXCEPTION_CATCHING_ALLOWED', [])
1326+
err = self.expect_fail([EMCC, test_file('hello_world.c')] + self.get_emcc_args())
1327+
self.assertContained('error: DISABLE_EXCEPTION_CATCHING and EXCEPTION_CATCHING_ALLOWED are mutually exclusive', err)
1328+
13081329
@with_both_exception_handling
13091330
def test_exceptions_uncaught(self):
13101331
# needs to flush stdio streams

tools/building.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -483,10 +483,10 @@ def llvm_backend_args():
483483
args = ['-combiner-global-alias-analysis=false']
484484

485485
# asm.js-style exception handling
486-
if Settings.DISABLE_EXCEPTION_CATCHING != 1:
486+
if not Settings.DISABLE_EXCEPTION_CATCHING:
487487
args += ['-enable-emscripten-cxx-exceptions']
488-
if Settings.DISABLE_EXCEPTION_CATCHING == 2:
489-
allowed = ','.join(Settings.EXCEPTION_CATCHING_ALLOWED or ['__fake'])
488+
if Settings.EXCEPTION_CATCHING_ALLOWED:
489+
allowed = ','.join(Settings.EXCEPTION_CATCHING_ALLOWED)
490490
args += ['-emscripten-cxx-exceptions-allowed=' + allowed]
491491

492492
if Settings.SUPPORT_LONGJMP:

0 commit comments

Comments
 (0)