summaryrefslogtreecommitdiff
path: root/gi
diff options
context:
space:
mode:
Diffstat (limited to 'gi')
-rw-r--r--gi/function.cpp56
-rw-r--r--gi/function.h3
-rw-r--r--gi/object.cpp6
-rw-r--r--gi/value.cpp26
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(&param_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;
}