summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMathieu Duponchelle <mathieu@centricular.com>2019-07-16 22:08:04 +0200
committerChristoph Reiter <reiter.christoph@gmail.com>2019-08-11 18:13:35 +0000
commita102f046a178472278522e3e9d7c0b40ecd52ade (patch)
tree398c92c4c0a6ed7edc74759b24f5e3a591ce9329
parentac576400ecd554879c906791e6638d64bb8bcc2a (diff)
downloadpygobject-a102f046a178472278522e3e9d7c0b40ecd52ade.tar.gz
pygobject-object: fix refcount of floating return values
When g_signal_emitv returns a floating reference as the return value, which we end up ref_sinking, do not unset the GValue, as we've taken ownership from it and don't want it to drop its reference. Adds a test that highlights the issue
-rw-r--r--gi/pygobject-object.c9
-rw-r--r--tests/regressextra.c40
-rw-r--r--tests/regressextra.h15
-rw-r--r--tests/test_signal.py5
4 files changed, 68 insertions, 1 deletions
diff --git a/gi/pygobject-object.c b/gi/pygobject-object.c
index 39c03ca3..bf969953 100644
--- a/gi/pygobject-object.c
+++ b/gi/pygobject-object.c
@@ -1935,8 +1935,15 @@ pygobject_emit(PyGObject *self, PyObject *args)
g_free(params);
if ((query.return_type & ~G_SIGNAL_TYPE_STATIC_SCOPE) != G_TYPE_NONE) {
+ gboolean was_floating = FALSE;
+
+ if (G_VALUE_HOLDS_OBJECT (&ret)) {
+ GObject *obj = g_value_get_object (&ret);
+ was_floating = g_object_is_floating (obj);
+ }
py_ret = pyg_value_as_pyobject(&ret, TRUE);
- g_value_unset(&ret);
+ if (!was_floating)
+ g_value_unset(&ret);
} else {
Py_INCREF(Py_None);
py_ret = Py_None;
diff --git a/tests/regressextra.c b/tests/regressextra.c
index d6af90bf..7e53373a 100644
--- a/tests/regressextra.c
+++ b/tests/regressextra.c
@@ -336,3 +336,43 @@ regress_test_cairo_matrix_out_caller_allocates (cairo_matrix_t *matrix)
}
#endif
+
+G_DEFINE_TYPE (RegressTestAction, regress_test_action, G_TYPE_INITIALLY_UNOWNED)
+
+enum
+{
+ SIGNAL_0,
+ ACTION_SIGNAL,
+ LAST_SIGNAL
+};
+
+static guint regress_test_action_signals[LAST_SIGNAL] = { 0 };
+
+static RegressTestAction *
+regress_test_action_do_action (RegressTestAction *self)
+{
+ RegressTestAction *ret = g_object_new (regress_test_action_get_type (), NULL);
+
+ return ret;
+}
+
+static void
+regress_test_action_init (RegressTestAction *self)
+{
+}
+
+static void regress_test_action_class_init (RegressTestActionClass *klass)
+{
+ /**
+ * RegressTestAction::action:
+ *
+ * An action signal.
+ *
+ * Returns: (transfer full): another #RegressTestAction
+ */
+ regress_test_action_signals[ACTION_SIGNAL] =
+ g_signal_new_class_handler ("action",
+ G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+ G_CALLBACK (regress_test_action_do_action), NULL, NULL,
+ NULL, regress_test_action_get_type (), 0);
+}
diff --git a/tests/regressextra.h b/tests/regressextra.h
index 0b40ab04..7fc30fe9 100644
--- a/tests/regressextra.h
+++ b/tests/regressextra.h
@@ -1,6 +1,8 @@
#ifndef REGRESS_EXTRA_H
#define REGRESS_EXTRA_H
+#include <glib-object.h>
+
typedef struct _RegressTestBoxedC RegressTestBoxedC;
typedef struct _RegressTestBoxedCWrapper RegressTestBoxedCWrapper;
@@ -62,4 +64,17 @@ void regress_test_cairo_matrix_out_caller_allocates (cairo_matrix_t *matrix);
#endif
+/* RegressTestAction */
+
+typedef struct {
+ GInitiallyUnowned parent;
+} RegressTestAction;
+
+typedef struct {
+ GInitiallyUnownedClass parent_class;
+} RegressTestActionClass;
+
+_GI_TEST_EXTERN
+GType regress_test_action_get_type (void);
+
#endif /* REGRESS_EXTRA_H */
diff --git a/tests/test_signal.py b/tests/test_signal.py
index 16d95c27..edc970fc 100644
--- a/tests/test_signal.py
+++ b/tests/test_signal.py
@@ -1243,6 +1243,11 @@ class TestIntrospectedSignals(unittest.TestCase):
# Boxed equality checks pointers by default.
self.assertNotEqual(struct, held_struct)
+ def test_action(self):
+ obj = Regress.TestAction()
+ other_obj = obj.emit('action')
+ self.assertEqual(other_obj.__grefcount__, 1)
+
class TestIntrospectedSignalsIssue158(unittest.TestCase):
"""