File: function-Always-initialize-callback-return-value.patch

package info (click to toggle)
gjs 1.74.2-1%2Bdeb12u1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 5,072 kB
  • sloc: cpp: 32,841; javascript: 26,083; sh: 1,428; python: 805; ansic: 741; xml: 106; makefile: 31
file content (66 lines) | stat: -rw-r--r-- 2,957 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
From: Sebastian Keller <skeller@gnome.org>
Date: Thu, 16 Mar 2023 22:35:49 +0100
Subject: function: Always initialize callback return value

When callback_closure() exits early, for example due to being called
during GC, the return value would not be initialized. This value is
often non-zero. If the callback is a source func of an idle or a timeout
this would then get interpreted as G_SOURCE_CONTINUE and the same would
repeat in the next iteration. If this happens fast enough, this results
in the entire process being seemingly frozen while spamming the log with
error messages.

To fix this always initialize the return value to 0 or a comparable
neutral value.

Related: https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/1868
Bug-Debian: https://bugs.debian.org/1034356
Forwarded: https://gitlab.gnome.org/GNOME/gjs/-/merge_requests/832
Applied-upstream: 1.77.1, commit:c925d91e5d018f38b0f66d0ac592274d4b007efb
---
 gi/function.cpp | 18 ++++++++----------
 1 file changed, 8 insertions(+), 10 deletions(-)

diff --git a/gi/function.cpp b/gi/function.cpp
index 08a0ea2..2fe4b2c 100644
--- a/gi/function.cpp
+++ b/gi/function.cpp
@@ -287,6 +287,14 @@ void GjsCallbackTrampoline::warn_about_illegal_js_callback(const char* when,
 void GjsCallbackTrampoline::callback_closure(GIArgument** args, void* result) {
     GITypeInfo ret_type;
 
+    // Fill in the result with some hopefully neutral value
+    g_callable_info_load_return_type(m_info, &ret_type);
+    if (g_type_info_get_tag(&ret_type) != GI_TYPE_TAG_VOID) {
+        GIArgument argument = {};
+        gjs_gi_argument_init_default(&ret_type, &argument);
+        set_return_ffi_arg_from_giargument(&ret_type, result, &argument);
+    }
+
     if (G_UNLIKELY(!is_valid())) {
         warn_about_illegal_js_callback(
             "during shutdown",
@@ -362,8 +370,6 @@ void GjsCallbackTrampoline::callback_closure(GIArgument** args, void* result) {
 
     JS::RootedValue rval(context);
 
-    g_callable_info_load_return_type(m_info, &ret_type);
-
     if (!callback_closure_inner(context, this_object, &rval, args, &ret_type,
                                 n_args, c_args_offset, result)) {
         if (!JS_IsExceptionPending(context)) {
@@ -384,14 +390,6 @@ void GjsCallbackTrampoline::callback_closure(GIArgument** args, void* result) {
                     m_info.ns(), m_info.name());
         }
 
-        // Fill in the result with some hopefully neutral value
-        if (g_type_info_get_tag(&ret_type) != GI_TYPE_TAG_VOID) {
-            GIArgument argument = {};
-            g_callable_info_load_return_type(m_info, &ret_type);
-            gjs_gi_argument_init_default(&ret_type, &argument);
-            set_return_ffi_arg_from_giargument(&ret_type, result, &argument);
-        }
-
         // If the callback has a GError** argument, then make a GError from the
         // value that was thrown. Otherwise, log it as "uncaught" (critical
         // instead of warning)