summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilip Chimento <philip.chimento@gmail.com>2021-08-26 22:47:00 -0700
committerPhilip Chimento <philip.chimento@gmail.com>2021-08-27 21:29:28 -0700
commitf478e264509d709ae9e8166525ae0f67b2e538e4 (patch)
treed0fccd7bc4874ededdc915861a483d70253d21d2
parent7313e015247fd1746f3e9c1fc2420b48d5029643 (diff)
downloadgjs-f478e264509d709ae9e8166525ae0f67b2e538e4.tar.gz
function: Warn about unhandled promise rejections in System.exit()
If we ran System.exit() inside a signal handler, then we do an abrupt exit without shutting down the JS engine. This means that we previously would swallow warnings about unhandled promise rejections when exiting from a signal handler. Instead, print them. See discussion in #417 for more info.
-rw-r--r--gi/function.cpp2
-rw-r--r--gjs/context-private.h3
-rwxr-xr-xinstalled-tests/scripts/testCommandLine.sh20
3 files changed, 22 insertions, 3 deletions
diff --git a/gi/function.cpp b/gi/function.cpp
index 4c9c649a..25fea26f 100644
--- a/gi/function.cpp
+++ b/gi/function.cpp
@@ -376,6 +376,8 @@ void GjsCallbackTrampoline::callback_closure(GIArgument** args, void* result) {
// main loop, or maybe not, but there's no way to tell, so we have
// to exit here instead of propagating the exception back to the
// original calling JS code.
+ gjs->warn_about_unhandled_promise_rejections();
+
uint8_t code;
if (gjs->should_exit(&code))
exit(code);
diff --git a/gjs/context-private.h b/gjs/context-private.h
index e29b495c..75b04bf0 100644
--- a/gjs/context-private.h
+++ b/gjs/context-private.h
@@ -136,8 +136,6 @@ class GjsContextPrivate : public JS::JobQueue {
void stop_draining_job_queue(void);
static gboolean drain_job_queue_idle_handler(void* data);
- void warn_about_unhandled_promise_rejections(void);
-
uint8_t handle_exit_code(const char* type, const char* identifier,
GError** error);
[[nodiscard]] bool auto_profile_enter(void);
@@ -245,6 +243,7 @@ class GjsContextPrivate : public JS::JobQueue {
GJS_JSAPI_RETURN_CONVENTION bool run_jobs_fallible(void);
void register_unhandled_promise_rejection(uint64_t id, GjsAutoChar&& stack);
void unregister_unhandled_promise_rejection(uint64_t id);
+ void warn_about_unhandled_promise_rejections();
void register_notifier(DestroyNotify notify_func, void* data);
void unregister_notifier(DestroyNotify notify_func, void* data);
diff --git a/installed-tests/scripts/testCommandLine.sh b/installed-tests/scripts/testCommandLine.sh
index 10eaea26..62be8243 100755
--- a/installed-tests/scripts/testCommandLine.sh
+++ b/installed-tests/scripts/testCommandLine.sh
@@ -103,6 +103,17 @@ const loop = new GLib.MainLoop(null, false);
loop.run();
EOF
+# this is similar to exit.js but should exit with an unhandled promise rejection
+cat <<EOF >promiseexit.js
+const {GLib} = imports.gi;
+const System = imports.system;
+const loop = GLib.MainLoop.new(null, false);
+Promise.reject();
+GLib.idle_add(GLib.PRIORITY_LOW, () => System.exit(42));
+GLib.timeout_add_seconds(GLib.PRIORITY_HIGH, 3, () => loop.quit());
+loop.run();
+EOF
+
total=0
report () {
@@ -156,8 +167,14 @@ if test -z $VALGRIND; then
ASAN_OPTIONS=detect_leaks=0 $gjs exit.js
test $? -ne 0
report "System.exit() should still exit across an FFI boundary"
+
+ # https://gitlab.gnome.org/GNOME/gjs/-/issues/417
+ output="$(ASAN_OPTIONS=detect_leaks=0 $gjs promiseexit.js 2>&1)"
+ test $? -ne 0 && printf '%s' "$output" | grep -q "Unhandled promise rejection"
+ report "Unhandled promise rejections should still be printed when exiting"
else
skip "System.exit() should still exit across an FFI boundary" "running under valgrind"
+ skip "Unhandled promise rejections should still be printed when exiting" "running under valgrind"
fi
# ensure the encoding of argv is being properly handled
@@ -323,6 +340,7 @@ else
skip "exit after first System.exit call in a signal callback" "running under valgrind"
fi
-rm -f exit.js help.js promise.js awaitcatch.js doublegi.js argv.js signalexit.js
+rm -f exit.js help.js promise.js awaitcatch.js doublegi.js argv.js \
+ signalexit.js promiseexit.js
echo "1..$total"