Gtk3 on m1 mac with monterey

Hi –

The following simple program gives a “Trace/BPT trap: 5” error when run on an M1 Mac with Monterey, using either python 2 or python 3.

import gi
gi.require_version("Gtk", "3.0")
from gi.repository import Gtk
w = Gtk.Window()

It works properly (ie doesn’t crash) on an Intel Mac with Big Sur. I used MacPorts to install all the relevant packages.

Can someone tell me if this works on other M1 Macs, with or with out MacPorts? If it does work elsewhere, what might I be doing wrong?

Here’s the stack

0   libsystem_c.dylib             	       0x18b4d8b6c __chk_fail_overflow + 24
1   libsystem_c.dylib             	       0x18b467b30 __memmove_chk + 40
2   libgtk-3.0.dylib              	       0x10502cf38 _gtk_marshal_VOID__OBJECT_OBJECTv + 52
3   libgobject-2.0.0.dylib        	       0x102e41324 _g_closure_invoke_va + 224
4   libgobject-2.0.0.dylib        	       0x102e56760 g_signal_emit_valist + 900
5   libgobject-2.0.0.dylib        	       0x102e56f30 g_signal_emit + 28
6   libgtk-3.0.dylib              	       0x104e08d2c gtk_css_node_reposition + 348
7   libgtk-3.0.dylib              	       0x104f4e5a0 gtk_style_context_save_named + 92
8   libgtk-3.0.dylib              	       0x104d64cd0 gtk_style_update_from_context + 100
9   libgtk-3.0.dylib              	       0x104d633b4 gtk_style_constructed + 40
10  libgobject-2.0.0.dylib        	       0x102e46fb8 g_object_new_internal + 256
11  libgobject-2.0.0.dylib        	       0x102e46c5c g_object_new_valist + 588
12  libgobject-2.0.0.dylib        	       0x102e46808 g_object_new + 32
13  libgtk-3.0.dylib              	       0x104d5f46c _gtk_style_new_for_path + 84
14  libgtk-3.0.dylib              	       0x104d5f4c0 gtk_style_new + 48
15  libgtk-3.0.dylib              	       0x104d61e64 gtk_widget_get_default_style + 60
16  libgtk-3.0.dylib              	       0x104fd944c gtk_widget_init + 284
17  libgobject-2.0.0.dylib        	       0x102e58438 g_type_create_instance + 328
18  libgobject-2.0.0.dylib        	       0x102e46f00 g_object_new_internal + 72
19  libgobject-2.0.0.dylib        	       0x102e4694c g_object_new_with_properties + 296

– Steve

I ran into the same issue on an M1 with Monterey when installing python and py39-gobject3 with MacPorts. I then used brew to install pygobject3, like so:

brew install pygobject3 gtk+3

I managed to display a simple example and did not crash until I closed the window. Here the output from the simple hello world with the “Click Here” button:

Hello World
Hello World
Segmentation fault: 11

I haven’t had time to explore further.

gedit and gnumeric don’t run on a M1 Mac with Monterey, at least not when installed with MacPorts. Can anyone tell me if they are expected to work? They fail with the same Trace/BPT trap: 5 error.

– Steve

Hi! It would be very helpful to get a stacktrace with debugging symbols. Can any of you build the GTK stack with jhbuild? See Projects/GTK/OSX/Building - GNOME Wiki!

It appears someone might have done it already. Here’s full back trace:

Great! Looks like the crash occurs when emitting a signal in gtk_css_node_reposition, either NODE_ADDED or NODE_REMOVED:

static void
gtk_css_node_reposition (GtkCssNode *node,
                         GtkCssNode *new_parent,
                         GtkCssNode *previous)
{
  /* ... */

  if (new_parent)
    {
      g_signal_emit (new_parent, cssnode_signals[NODE_ADDED], 0, node, previous);
      if (node->visible)
        gtk_css_node_invalidate (new_parent->first_child, GTK_CSS_CHANGE_NTH_LAST_CHILD);
    }

  /* ... */
}

The signals are defined as:

  cssnode_signals[NODE_ADDED] =
    g_signal_new (I_("node-added"),
		  G_TYPE_FROM_CLASS (object_class),
		  G_SIGNAL_RUN_LAST,
                  G_STRUCT_OFFSET (GtkCssNodeClass, node_added),
		  NULL, NULL,
		  _gtk_marshal_VOID__OBJECT_OBJECT,
		  G_TYPE_NONE, 2,
		  GTK_TYPE_CSS_NODE, GTK_TYPE_CSS_NODE);
  g_signal_set_va_marshaller (cssnode_signals[NODE_ADDED],
                              G_TYPE_FROM_CLASS (klass),
                              _gtk_marshal_VOID__OBJECT_OBJECTv);

Interestingly enough, those are the only signals using the _gtk_marshal_VOID__OBJECT_OBJECTv marshaller in all of GTK. I wonder if that marshaller is causing the crash on Mac M1. We could try removing the call to g_signal_set_va_marshaller to use the FFI-based one.

Here’s the code:

void
_gtk_marshal_VOID__OBJECT_OBJECTv (GClosure *closure,
                                   GValue   *return_value G_GNUC_UNUSED,
                                   gpointer  instance,
                                   va_list   args,
                                   gpointer  marshal_data,
                                   int       n_params,
                                   GType    *param_types)
{
  typedef void (*GMarshalFunc_VOID__OBJECT_OBJECT) (gpointer data1,
                                                    gpointer arg1,
                                                    gpointer arg2,
                                                    gpointer data2);
  GCClosure *cc = (GCClosure *) closure;
  gpointer data1, data2;
  GMarshalFunc_VOID__OBJECT_OBJECT callback;
  gpointer arg0;
  gpointer arg1;
  va_list args_copy;

  G_VA_COPY (args_copy, args);
  arg0 = (gpointer) va_arg (args_copy, gpointer);
  if (arg0 != NULL)
    arg0 = g_object_ref (arg0);
  arg1 = (gpointer) va_arg (args_copy, gpointer);
  if (arg1 != NULL)
    arg1 = g_object_ref (arg1);
  va_end (args_copy);


  if (G_CCLOSURE_SWAP_DATA (closure))
    {
      data1 = closure->data;
      data2 = instance;
    }
  else
    {
      data1 = instance;
      data2 = closure->data;
    }
  callback = (GMarshalFunc_VOID__OBJECT_OBJECT) (marshal_data ? marshal_data : cc->callback);

  callback (data1,
            arg0,
            arg1,
            data2);
  if (arg0 != NULL)
    g_object_unref (arg0);
  if (arg1 != NULL)
    g_object_unref (arg1);
}

According to the stacktrace the error is in G_VA_COPY

The definition of G_VA_COPY comes from meson.build in GLib:

# === va_copy checks ===
# we currently check for all three va_copy possibilities, so we get
# all results in config.log for bug reports.

va_copy_func = ''
foreach try_func : [ '__va_copy', 'va_copy' ]
  if cc.compiles('''#include <stdarg.h>
                    #include <stdlib.h>
                    #ifdef _MSC_VER
                    # include "msvc_recommended_pragmas.h"
                    #endif
                    void f (int i, ...) {
                    va_list args1, args2;
                    va_start (args1, i);
                    @0@ (args2, args1);
                    if (va_arg (args2, int) != 42 || va_arg (args1, int) != 42)
                      exit (1);
                    va_end (args1); va_end (args2);
                    }
                    int main() {
                      f (0, 42);
                      return 0;
                    }'''.format(try_func),
                    name : try_func + ' check')
    va_copy_func = try_func
  endif
endforeach
if va_copy_func != ''
  glib_conf.set('G_VA_COPY', va_copy_func)
  glib_vacopy = '#define G_VA_COPY ' + va_copy_func
else
  glib_vacopy = '/* #undef G_VA_COPY */'
endif

va_list_val_copy_prog = '''
  #include <stdarg.h>
  #include <stdlib.h>
  void f (int i, ...) {
    va_list args1, args2;
    va_start (args1, i);
    args2 = args1;
    if (va_arg (args2, int) != 42 || va_arg (args1, int) != 42)
      exit (1);
    va_end (args1); va_end (args2);
  }
  int main() {
    f (0, 42);
    return 0;
  }'''

if cc_can_run
  rres = cc.run(va_list_val_copy_prog, name : 'va_lists can be copied as values')
  glib_va_val_copy = rres.returncode() == 0
else
  glib_va_val_copy = meson.get_cross_property('va_val_copy', true)
endif
if not glib_va_val_copy
  glib_vacopy = glib_vacopy + '\n#define G_VA_COPY_AS_ARRAY 1'
  glib_conf.set('G_VA_COPY_AS_ARRAY', 1)
endif
glibconfig_conf.set('glib_vacopy', glib_vacopy)

Or from glib/gutils.h:

/* Define G_VA_COPY() to do the right thing for copying va_list variables.
 * glibconfig.h may have already defined G_VA_COPY as va_copy or __va_copy.
 */
#if !defined (G_VA_COPY)
#  if defined (__GNUC__) && defined (__PPC__) && (defined (_CALL_SYSV) || defined (_WIN32))
#    define G_VA_COPY(ap1, ap2)	  (*(ap1) = *(ap2))
#  elif defined (G_VA_COPY_AS_ARRAY)
#    define G_VA_COPY(ap1, ap2)	  memmove ((ap1), (ap2), sizeof (va_list))
#  else /* va_list is a pointer */
#    define G_VA_COPY(ap1, ap2)	  ((ap1) = (ap2))
#  endif /* va_list is a pointer */
#endif /* !G_VA_COPY */

See also:

Opened an issue on GitLab: https://gitlab.gnome.org/GNOME/glib/-/issues/2570

Also void string string_v is impacted:

Thread 0 Crashed::  Dispatch queue: com.apple.main-thread
0   libsystem_c.dylib             	       0x1bc2b0b6c __chk_fail_overflow + 24
1   libsystem_c.dylib             	       0x1bc23fb30 __memmove_chk + 40
2   libgtk-3.0.dylib              	       0x1065f97e4 _gtk_marshal_VOID__STRING_STRINGv + 56
3   libgobject-2.0.0.dylib        	       0x102fb5458 _g_closure_invoke_va + 224
4   libgobject-2.0.0.dylib        	       0x102fca6f0 g_signal_emit_valist + 852
5   libgobject-2.0.0.dylib        	       0x102fcaf3c g_signal_emit + 28
6   libgtk-3.0.dylib              	       0x10635c7b4 gtk_action_muxer_primary_accel_changed + 128
7   libgtk-3.0.dylib              	       0x106372d9c gtk_application_set_accels_for_action + 132
8   libgtk-3.0.dylib              	       0x1065ea9dc gtk_application_impl_quartz_startup + 212
9   libgtk-3.0.dylib              	       0x1063743d4 gtk_application_startup + 124
10  libgobject-2.0.0.dylib        	       0x102fb5458 _g_closure_invoke_va + 224
11  libgobject-2.0.0.dylib        	       0x102fca6f0 g_signal_emit_valist + 852
12  libgobject-2.0.0.dylib        	       0x102fcaf3c g_signal_emit + 28
13  libgio-2.0.0.dylib            	       0x1038cebb8 g_application_register + 244
14  libgiomm-2.4.1.dylib          	       0x10554bcc4 Gio::Application::register_application() + 44
15  libinkscape_base.dylib        	       0x104883bfc InkscapeApplication::InkscapeApplication() + 7488
16  libinkscape_base.dylib        	       0x104881c8c InkscapeApplication::singleton() + 56
17  inkscape                      	       0x102aa2980 main + 7164
18  dyld                          	       0x102b010f4 start + 520

Can anybody try compiling GLib with Meson and post the meson log here? That would be very useful!

I cannot upload as a new user and text is to long to paste either. Discourse is making it difficult.

Thanks! Yes, there are some limitations here on Discourse; let’s use Gitlab then: https://gitlab.gnome.org/GNOME/glib/-/issues/2570

Isn’t that snippet all you are looking for though?

Code:
 #include <stdarg.h>
                    #include <stdlib.h>
                    #ifdef _MSC_VER
                    # include "msvc_recommended_pragmas.h"
                    #endif
                    void f (int i, ...) {
                    va_list args1, args2;
                    va_start (args1, i);
                    __va_copy (args2, args1);
                    if (va_arg (args2, int) != 42 || va_arg (args1, int) != 42)
                      exit (1);
                    va_end (args1); va_end (args2);
                    }
                    int main() {
                      f (0, 42);
                      return 0;
                    }
Compiler stdout:
 
Compiler stderr:
 
Checking if "__va_copy check" compiles: YES 
Running compile:
Working directory:  /Users/mike/dev/glib/_build/meson-private/tmp1caw8wh6
Command line:  ccache cc /Users/mike/dev/glib/_build/meson-private/tmp1caw8wh6/testfile.c -o /Users/mike/dev/glib/_build/meson-private/tmp1caw8wh6/output.obj -c -O0 -Werror=unknown-warning-option -Werror=unused-command-line-argument -Werror=ignored-optimization-argument -std=gnu99 

Code:
 #include <stdarg.h>
                    #include <stdlib.h>
                    #ifdef _MSC_VER
                    # include "msvc_recommended_pragmas.h"
                    #endif
                    void f (int i, ...) {
                    va_list args1, args2;
                    va_start (args1, i);
                    va_copy (args2, args1);
                    if (va_arg (args2, int) != 42 || va_arg (args1, int) != 42)
                      exit (1);
                    va_end (args1); va_end (args2);
                    }
                    int main() {
                      f (0, 42);
                      return 0;
                    }
Compiler stdout:
 
Compiler stderr:
 
Checking if "va_copy check" compiles: YES 

Yep. Opened #64377 (GLib2 not working on Apple Silicon) – MacPorts