diff options
Diffstat (limited to 'gi')
-rw-r--r-- | gi/function.cpp | 56 | ||||
-rw-r--r-- | gi/function.h | 3 | ||||
-rw-r--r-- | gi/object.cpp | 6 | ||||
-rw-r--r-- | gi/value.cpp | 26 |
4 files changed, 51 insertions, 40 deletions
diff --git a/gi/function.cpp b/gi/function.cpp index 1629876b..3fb87939 100644 --- a/gi/function.cpp +++ b/gi/function.cpp @@ -8,6 +8,7 @@ #include <stdlib.h> // for exit #include <memory> // for unique_ptr +#include <sstream> #include <string> #include <vector> @@ -47,7 +48,6 @@ #include "gi/object.h" #include "gi/utils-inl.h" #include "gjs/context-private.h" -#include "gjs/context.h" #include "gjs/global.h" #include "gjs/jsapi-util.h" #include "gjs/macros.h" @@ -270,13 +270,21 @@ set_return_ffi_arg_from_giargument (GITypeInfo *ret_type, } void GjsCallbackTrampoline::warn_about_illegal_js_callback(const char* when, - const char* reason) { - g_critical("Attempting to run a JS callback %s. This is most likely caused " - "by %s. Because it would crash the application, it has been " - "blocked.", when, reason); - if (m_info) - g_critical("The offending callback was %s()%s.", m_info.name(), - m_is_vfunc ? ", a vfunc" : ""); + const char* reason, + bool dump_stack) { + std::ostringstream message; + + message << "Attempting to run a JS callback " << when << ". " + << "This is most likely caused by " << reason << ". " + << "Because it would crash the application, it has been blocked."; + if (m_info) { + message << "\nThe offending callback was " << m_info.name() << "()" + << (m_is_vfunc ? ", a vfunc." : "."); + } + if (dump_stack) { + message << "\n" << gjs_dumpstack_string(); + } + g_critical("%s", message.str().c_str()); } /* This is our main entry point for ffi_closure callbacks. @@ -289,12 +297,20 @@ 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", "destroying a Clutter actor or GTK widget with ::destroy signal " - "connected, or using the destroy(), dispose(), or remove() vfuncs"); - gjs_dumpstack(); + "connected, or using the destroy(), dispose(), or remove() vfuncs", + true); return; } @@ -304,14 +320,15 @@ void GjsCallbackTrampoline::callback_closure(GIArgument** args, void* result) { warn_about_illegal_js_callback( "during garbage collection", "destroying a Clutter actor or GTK widget with ::destroy signal " - "connected, or using the destroy(), dispose(), or remove() vfuncs"); - gjs_dumpstack(); + "connected, or using the destroy(), dispose(), or remove() vfuncs", + true); return; } if (G_UNLIKELY(!gjs->is_owner_thread())) { warn_about_illegal_js_callback("on a different thread", - "an API not intended to be used in JS"); + "an API not intended to be used in JS", + false); return; } @@ -351,7 +368,8 @@ void GjsCallbackTrampoline::callback_closure(GIArgument** args, void* result) { if (g_object_get_qdata(gobj, ObjectBase::disposed_quark())) { warn_about_illegal_js_callback( "on disposed object", - "using the destroy(), dispose(), or remove() vfuncs"); + "using the destroy(), dispose(), or remove() vfuncs", + false); } gjs_log_exception(context); return; @@ -365,8 +383,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, gobj, &rval, args, &ret_type, n_args, c_args_offset, result)) { if (!JS_IsExceptionPending(context)) { @@ -389,14 +405,6 @@ void GjsCallbackTrampoline::callback_closure(GIArgument** args, void* result) { descr.c_str(), 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) diff --git a/gi/function.h b/gi/function.h index c875ecbd..b9ee87be 100644 --- a/gi/function.h +++ b/gi/function.h @@ -79,7 +79,8 @@ struct GjsCallbackTrampoline : public Gjs::Closure { GObject* gobject, JS::MutableHandleValue rval, GIArgument** args, GITypeInfo* ret_type, int n_args, int c_args_offset, void* result); - void warn_about_illegal_js_callback(const char* when, const char* reason); + void warn_about_illegal_js_callback(const char* when, const char* reason, + bool dump_stack); static std::vector<GjsAutoGClosure> s_forever_closure_list; diff --git a/gi/object.cpp b/gi/object.cpp index 62e79c18..1ad12afe 100644 --- a/gi/object.cpp +++ b/gi/object.cpp @@ -58,7 +58,6 @@ #include "gi/wrapperutils.h" #include "gjs/atoms.h" #include "gjs/context-private.h" -#include "gjs/context.h" #include "gjs/deprecation.h" #include "gjs/jsapi-class.h" #include "gjs/jsapi-util.h" @@ -165,10 +164,9 @@ bool ObjectInstance::check_gobject_disposed_or_finalized( "Object %s.%s (%p), has been already %s — impossible to %s " "it. This might be caused by the object having been destroyed from C " "code using something such as destroy(), dispose(), or remove() " - "vfuncs.", + "vfuncs.\n%s", ns(), name(), m_ptr.get(), m_gobj_finalized ? "finalized" : "disposed", - for_what); - gjs_dumpstack(); + for_what, gjs_dumpstack_string().c_str()); return false; } diff --git a/gi/value.cpp b/gi/value.cpp index 17db002f..59237f1e 100644 --- a/gi/value.cpp +++ b/gi/value.cpp @@ -7,6 +7,7 @@ #include <stdint.h> #include <stdlib.h> // for exit +#include <sstream> #include <string> #include <girepository.h> @@ -46,7 +47,6 @@ #include "gjs/atoms.h" #include "gjs/byteArray.h" #include "gjs/context-private.h" -#include "gjs/context.h" #include "gjs/jsapi-util.h" #include "gjs/macros.h" #include "gjs/objectbox.h" @@ -142,22 +142,26 @@ void Gjs::Closure::marshal(GValue* return_value, unsigned n_param_values, GjsContextPrivate* gjs = GjsContextPrivate::from_cx(context); if (G_UNLIKELY(gjs->sweeping())) { GSignalInvocationHint *hint = (GSignalInvocationHint*) invocation_hint; - - g_critical("Attempting to call back into JSAPI during the sweeping phase of GC. " - "This is most likely caused by not destroying a Clutter actor or Gtk+ " - "widget with ::destroy signals connected, but can also be caused by " - "using the destroy(), dispose(), or remove() vfuncs. " - "Because it would crash the application, it has been " - "blocked and the JS callback not invoked."); + std::ostringstream message; + + message << "Attempting to call back into JSAPI during the sweeping " + "phase of GC. This is most likely caused by not destroying " + "a Clutter actor or Gtk+ widget with ::destroy signals " + "connected, but can also be caused by using the destroy(), " + "dispose(), or remove() vfuncs. Because it would crash the " + "application, it has been blocked and the JS callback not " + "invoked."; if (hint) { gpointer instance; g_signal_query(hint->signal_id, &signal_query); instance = g_value_peek_pointer(¶m_values[0]); - g_critical("The offending signal was %s on %s %p.", signal_query.signal_name, - g_type_name(G_TYPE_FROM_INSTANCE(instance)), instance); + message << "\nThe offending signal was " << signal_query.signal_name + << " on " << g_type_name(G_TYPE_FROM_INSTANCE(instance)) + << " " << instance << "."; } - gjs_dumpstack(); + message << "\n" << gjs_dumpstack_string(); + g_critical("%s", message.str().c_str()); return; } |