[perl-Gtk2] Gtk2::Menu: trap exceptions in popup callbacks
- From: Torsten Schönfeld <tsch src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [perl-Gtk2] Gtk2::Menu: trap exceptions in popup callbacks
- Date: Sun, 25 Apr 2010 15:15:11 +0000 (UTC)
commit f99e67667d6453f753f8588ca837984752521622
Author: Kevin Ryde <user42 zip com au>
Date: Sun Apr 25 17:11:33 2010 +0200
Gtk2::Menu: trap exceptions in popup callbacks
Uncaught exceptions in a popup callback can result in persistent mouse and
keyboard grabs, locking the screen until the program is killed.
https://bugzilla.gnome.org/show_bug.cgi?id=613973
t/GtkMenu.t | 19 ++++++++++++++++++-
xs/GtkMenu.xs | 38 ++++++++++++++++++++++++--------------
2 files changed, 42 insertions(+), 15 deletions(-)
---
diff --git a/t/GtkMenu.t b/t/GtkMenu.t
index 27b4cd7..61874bd 100644
--- a/t/GtkMenu.t
+++ b/t/GtkMenu.t
@@ -8,7 +8,7 @@
# - rm
#########################
-use Gtk2::TestHelper tests => 64;
+use Gtk2::TestHelper tests => 66;
ok( my $menubar = Gtk2::MenuBar->new );
@@ -171,6 +171,23 @@ unless ($i_know_you) {
is ($detach_func, undef, 'detach callback func freed after called');
}
+{
+ my $popup_runs = 0;
+ my $saw_warning = '';
+ { local $SIG{__WARN__} = sub { $saw_warning = $_[0] };
+ $menu->popup(undef, undef, sub {
+ $popup_runs = 1;
+ die;
+ }, undef, 1, 0);
+ }
+ diag "popup position runs=$popup_runs warn='$saw_warning'";
+ $menu->popdown;
+ ok ($popup_runs,
+ 'popup positioning die() - popup runs');
+ ok ($saw_warning,
+ 'popup positioning die() - die not fatal, turned into warning');
+}
+
SKIP: {
skip 'new 2.14 stuff', 2
unless Gtk2->CHECK_VERSION(2, 14, 0);
diff --git a/xs/GtkMenu.xs b/xs/GtkMenu.xs
index 283e39b..ee6d20d 100644
--- a/xs/GtkMenu.xs
+++ b/xs/GtkMenu.xs
@@ -57,24 +57,34 @@ gtk2perl_menu_position_func (GtkMenu * menu,
if (callback->data)
XPUSHs (sv_2mortal (newSVsv (callback->data)));
- PUTBACK;
-
- n = call_sv (callback->func, G_ARRAY);
+ /* A die() from callback->func is suspected to be bad or very bad.
+ Circa Gtk 2.18 a jump out of $menu->popup seems to leave an X
+ grab with no way to get rid of it (no keyboard Esc, and no mouse
+ click handlers). The position func can also be called later for
+ things like resizing or move to a different GdkScreen, and such a
+ call might come straight from the main loop, where a die() would
+ jump out of Gtk2->main. */
+ PUTBACK;
+ n = call_sv (callback->func, G_ARRAY | G_EVAL);
SPAGAIN;
- if (n < 2 || n > 3)
- croak ("menu position callback must return two integers "
- "(x, and y) or two integers and a boolean (x, y, and "
- "push_in)");
-
- /* POPs and POPi take things off the *end* of the stack! */
- if (n > 2) {
- SV *sv = POPs;
- *push_in = sv_2bool (sv);
+ if (SvTRUE (ERRSV)) {
+ g_warning ("menu position callback ignoring error: %s",
+ SvPVutf8_nolen (ERRSV));
+ } else if (n < 2 || n > 3) {
+ g_warning ("menu position callback must return two integers "
+ "(x, and y) or two integers and a boolean "
+ "(x, y, and push_in)");
+ } else {
+ /* POPs and POPi take things off the *end* of the stack! */
+ if (n > 2) {
+ SV *sv = POPs;
+ *push_in = sv_2bool (sv);
+ }
+ if (n > 1) *y = POPi;
+ if (n > 0) *x = POPi;
}
- if (n > 1) *y = POPi;
- if (n > 0) *x = POPi;
PUTBACK;
FREETMPS;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]