Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Xliff/010d1ea5a92ea6e3524e70f0a1b4b77a to your computer and use it in GitHub Desktop.
Save Xliff/010d1ea5a92ea6e3524e70f0a1b4b77a to your computer and use it in GitHub Desktop.
Weird Error in GTK Signal Handling...

I'm getting the following error from a simple GTK Widget test that used to report errors, properly.

The code for that is relatively simple, so I will include it here:

use v6.c;

use Test;

use NativeCall;

use GTK::Application;
use GTK::Button;
#use GTK::Box;

my $a = GTK::Application.new(
  title  => 'org.genex.test.widget',
  width  => 400,
  height => 400
);

$a.activate.tap({
  my $box = GTK::Box.new-vbox(6);
  my ($b1, $b2, $b3) = (
    GTK::Button.new_with_label('Click Me'),
    GTK::Button.new_with_mnemonic('_Open'),
    GTK::Button.new_with_mnemonic('_Close')
  );
  
  die;

  $a.window.add($box);
  $b1.clicked.tap({ say 'Click me button was clicked'; });
  $b2.clicked.tap({ say 'Open button was clicked'; });
  $b3.clicked.tap({ say 'Closing application.'; $a.exit; });
  $box.pack_start($b1, True, True, 0);
  $box.pack_start($b2, True, True, 0);
  $box.pack_start($b3, True, True, 0);
  $a.show_all;
});

$a.run;

This should return something like:

Died
  in block <unit> at t/01-widget.t line 26

Instead, I am getting:

MoarVM panic: Internal error: Unwound entire stack and missed handler

Well, it turns out that this resulted from something very simple. Here is a generic signal handler:

method connect(
    $obj,
    $signal,
    &handler?
  ) {
    my $hid;
    %!signals{$signal} //= do {
      my $s = Supplier.new;
      #"O: $obj".say;
      #"S: $signal".say;
      $hid = g_signal_connect_wd($obj, $signal,
        -> $, $ {
            $s.emit(self);
            CATCH { default { $s.quit($_ } }
        },
        OpaquePointer, 0
      );
      [ $s.Supply, $obj, $hid];
    };
    %!signals{$signal}[0].tap(&handler) with &handler;
    %!signals{$signal}[0];
  }

Compare that with this change when invoking g_signal_connect_wd:

$hid = g_signal_connect_wd($obj, $signal,
  -> $, $ {
      $s.emit(self);
      CATCH { default { note $_ } }
  },
  OpaquePointer, 0
);

The difference: the call to $s.quit, which is supposed to be the proper way to dispose of a Supplier. This will crash Rakudo, whereas just reporting the exception via "note" will not. This prevents valuable error messages from being reported back to the user. Is this a Rakudo problem that should be bugged?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment