[gjs: 1/2] function: Warn about unhandled promise rejections in System.exit()




commit f478e264509d709ae9e8166525ae0f67b2e538e4
Author: Philip Chimento <philip chimento gmail com>
Date:   Thu Aug 26 22:47:00 2021 -0700

    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.

 gi/function.cpp                            |  2 ++
 gjs/context-private.h                      |  3 +--
 installed-tests/scripts/testCommandLine.sh | 20 +++++++++++++++++++-
 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"


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]