[gjs/mozjs31: 7/7] js: Don't exit immediately from System.exit()



commit aa3d22239ac6d6e872c11d8c75e329c752c40ced
Author: Philip Chimento <philip endlessm com>
Date:   Mon Nov 14 16:46:17 2016 -0800

    js: Don't exit immediately from System.exit()
    
    Exiting directly will now crash the GC thread if there happens to be a GC
    going on at the time exit() is called; you can force this by running e.g.
    
        JS_GC_ZEAL=2,1 gjs -c 'imports.system.exit(0)'
    
    on a debug build of SpiderMonkey.
    
    This does what SpiderMonkey's shell itself does: sets a flag to tell the
    interpreter that the script wants to exit, then throws an uncatchable
    exception. When JS::Evaluate subsequently exits, the flag is checked and
    exit() is called.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=751252

 gjs/context-private.h |    8 ++++++++
 gjs/context.cpp       |   25 +++++++++++++++++++++++++
 modules/system.cpp    |    7 +++++--
 3 files changed, 38 insertions(+), 2 deletions(-)
---
diff --git a/gjs/context-private.h b/gjs/context-private.h
index 10d000a..045909f 100644
--- a/gjs/context-private.h
+++ b/gjs/context-private.h
@@ -24,6 +24,8 @@
 #ifndef __GJS_CONTEXT_PRIVATE_H__
 #define __GJS_CONTEXT_PRIVATE_H__
 
+#include <inttypes.h>
+
 #include "context.h"
 
 G_BEGIN_DECLS
@@ -32,6 +34,12 @@ bool         _gjs_context_destroying                  (GjsContext *js_context);
 
 void         _gjs_context_schedule_gc_if_needed       (GjsContext *js_context);
 
+void _gjs_context_exit(GjsContext *js_context,
+                       uint8_t     exit_code);
+
+bool _gjs_context_should_exit(GjsContext *js_context,
+                              uint8_t    *exit_code_p);
+
 G_END_DECLS
 
 #endif  /* __GJS_CONTEXT_PRIVATE_H__ */
diff --git a/gjs/context.cpp b/gjs/context.cpp
index 682d00c..5c8c267 100644
--- a/gjs/context.cpp
+++ b/gjs/context.cpp
@@ -69,6 +69,9 @@ struct _GjsContext {
 
     bool destroying;
 
+    bool should_exit;
+    uint8_t exit_code;
+
     guint    auto_gc_id;
 
     jsid const_strings[GJS_STRING_LAST];
@@ -556,6 +559,24 @@ _gjs_context_schedule_gc_if_needed (GjsContext *js_context)
                                              js_context, NULL);
 }
 
+void
+_gjs_context_exit(GjsContext *js_context,
+                  uint8_t     exit_code)
+{
+    g_assert(!js_context->should_exit);
+    js_context->should_exit = true;
+    js_context->exit_code = exit_code;
+}
+
+bool
+_gjs_context_should_exit(GjsContext *js_context,
+                         uint8_t    *exit_code_p)
+{
+    if (exit_code_p != NULL)
+        *exit_code_p = js_context->exit_code;
+    return js_context->should_exit;
+}
+
 /**
  * gjs_context_maybe_gc:
  * @context: a #GjsContext
@@ -649,6 +670,10 @@ gjs_context_eval(GjsContext   *js_context,
     JS::RootedValue retval(js_context->context);
     if (!gjs_eval_with_scope(js_context->context, JS::NullPtr(), script,
                              script_len, filename, &retval)) {
+        uint8_t code;
+        if (_gjs_context_should_exit(js_context, &code))
+            exit(code);
+
         gjs_log_exception(js_context->context);
         g_set_error(error,
                     GJS_ERROR,
diff --git a/modules/system.cpp b/modules/system.cpp
index 4c49799..c2c1551 100644
--- a/modules/system.cpp
+++ b/modules/system.cpp
@@ -31,6 +31,7 @@
 #include <gjs/context.h>
 
 #include "gi/object.h"
+#include "gjs/context-private.h"
 #include "gjs/jsapi-util-args.h"
 #include "system.h"
 
@@ -116,8 +117,10 @@ gjs_exit(JSContext *context,
     if (!gjs_parse_call_args(context, "exit", argv, "i",
                              "ecode", &ecode))
         return false;
-    exit(ecode);
-    return true;
+
+    GjsContext *gjs_context = static_cast<GjsContext *>(JS_GetContextPrivate(context));
+    _gjs_context_exit(gjs_context, ecode);
+    return false;  /* without gjs_throw() == "throw uncatchable exception" */
 }
 
 static bool


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