Subject: Re: bug#56869: 29.0.50; segfault, "assertion 'GDK_IS_DEVICE (device)' failed"

From: Joe Corneli <[email-masked]>
Date: Thu, 18 Aug 2022 14:20:27 +0100

Po Lu writes:

> Joe Corneli <[email-masked]> writes:
>
>> Joe Corneli writes:
>>>
>>> In light of the previous, I think this is what’s needed.  Details will
>>> be forthcoming with the next crash!
>>>
>>> joe@Proteus:~$  sudo apt-get source libgtk-3-0
>>
>> OK, here’s the next round of backtrace.  Now it includes some Lisp
>> details, implicating feebleline (https://melpa.org/#/feebleline) as the
>> source of the problems.
>
> Async input can be read almost anywhere, and that includes from Lisp.
> So feebleline is most likely not the problem here.

For now, I’ve turned off the feature that seemed most suspicious...
https://github.com/tautologyclub/feebleline/issues/66

If it turns out that I don’t have any crashes then great!  Otherwise,
more reports will surely follow.

> As I said, the line number is unfortunately not very informative, so
> please type "l" to show a listing of the GDK code at that particular
> line.
>
> Thanks.

Sure, though I forgot to save the core file last time, so I can’t press
"l" in gdb, but here are indicative code snippets from the files named
in the previous backtrace.  The mentioned lines are marked below:

...  M-x occur RET /\*[0-9]+\*/ RET

Thank you!

>> #0  gdk_x11_device_manager_xi2_translate_event
>>     (xevent=<optimised out>, event=<optimised out>, display=<optimised out>, translator=<optimised out>)
>>     at ../../../../../gdk/x11/gdkdevicemanager-xi2.c:1794

        event->motion.type = GDK_MOTION_NOTIFY;
        event->motion.window = window;
        event->motion.time = xev->time;
        event->motion.x = (gdouble) xev->event_x / scale;
        event->motion.y = (gdouble) xev->event_y / scale;
        event->motion.x_root = (gdouble) xev->root_x / scale;
        event->motion.y_root = (gdouble) xev->root_y / scale;

        event->motion.device = device;
        gdk_event_set_source_device (event, source_device);
        gdk_event_set_seat (event, gdk_device_get_seat (device));
        gdk_event_set_device_tool (event, source_device->last_tool); /*1794*/

        event->motion.state = _gdk_x11_device_xi2_translate_state (&xev->mods, &xev->buttons, &xev->group);

#ifdef XINPUT_2_2
        if (xev->flags & XIPointerEmulated)
          gdk_event_set_pointer_emulated (event, TRUE);
#endif

>> #1  gdk_x11_device_manager_xi2_translate_event
>>     (translator=<optimised out>, display=<optimised out>, event=<optimised out>, xevent=<optimised out>)
>>     at ../../../../../gdk/x11/gdkdevicemanager-xi2.c:1478

static gboolean
gdk_x11_device_manager_xi2_translate_event (GdkEventTranslator *translator, /*1478*/
                                            GdkDisplay         *display,
                                            GdkEvent           *event,
                                            XEvent             *xevent)
{
  GdkX11DeviceManagerXI2 *device_manager;
  XGenericEventCookie *cookie;
  GdkDevice *device, *source_device;
  gboolean return_val = TRUE;
  GdkWindow *window;
  GdkWindowImplX11 *impl;
  int scale;
  XIEvent *ev;
/*...*/

>> #2  0x00007ffff757e989 in _gdk_x11_event_translator_translate
>>     (translator=translator@entry=0x55555647e400, display=0x55555645a0e0, xevent=xevent@entry=0x7ffffffe9730)
>>     at ../../../../../gdk/x11/gdkeventtranslator.c:51

GdkEvent *
_gdk_x11_event_translator_translate (GdkEventTranslator *translator,
                                     GdkDisplay         *display,
                                     XEvent             *xevent)
{
  GdkEventTranslatorIface *iface;
  GdkEvent *event;

  g_return_val_if_fail (GDK_IS_EVENT_TRANSLATOR (translator), NULL);
  g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);

  iface = GDK_EVENT_TRANSLATOR_GET_IFACE (translator);

  if (!iface->translate_event)
    return NULL;

  event = gdk_event_new (GDK_NOTHING);

  if ((iface->translate_event) (translator, display, event, xevent)) /*51*/
    return event;

  gdk_event_free (event);

  return NULL;
}

>> #3  0x00007ffff757e4cc in gdk_event_source_translate_event (xevent=0x7ffffffe9730, event_source=0x55555648b380)
>>     at ../../../../../gdk/x11/gdkeventsource.c:230

static GdkEvent *
gdk_event_source_translate_event (GdkEventSource *event_source,
                                  XEvent         *xevent)
{
  GdkEvent *event = gdk_event_new (GDK_NOTHING);
  GdkFilterReturn result = GDK_FILTER_CONTINUE;
  GdkEventTranslator *event_translator;
  GdkWindow *filter_window;
  Display *dpy;

  dpy = GDK_DISPLAY_XDISPLAY (event_source->display);

#ifdef HAVE_XGENERICEVENTS
  /* Get cookie data here so it's available
   * to every event translator and event filter.
   */
  if (xevent->type == GenericEvent)
    XGetEventData (dpy, &xevent->xcookie);
#endif

  filter_window = gdk_event_source_get_filter_window (event_source, xevent,
                                                      &event_translator);
  if (filter_window)
    event->any.window = g_object_ref (filter_window);

  /* Run default filters */
  if (_gdk_default_filters)
    {
      /* Apply global filters */
      result = gdk_event_apply_filters (xevent, event, NULL);
    }

  if (result == GDK_FILTER_CONTINUE &&
      filter_window && filter_window->filters)
    {
      /* Apply per-window filters */
      result = gdk_event_apply_filters (xevent, event, filter_window);
    }

  if (result != GDK_FILTER_CONTINUE)
    {
#ifdef HAVE_XGENERICEVENTS
      if (xevent->type == GenericEvent)
        XFreeEventData (dpy, &xevent->xcookie);
#endif

      if (result == GDK_FILTER_REMOVE)
        {
          gdk_event_free (event);
          return NULL;
        }
      else /* GDK_FILTER_TRANSLATE */
        return event;
    }

  gdk_event_free (event);
  event = NULL;

  if (event_translator)
    {
      /* Event translator was gotten before in get_filter_window() */
      event = _gdk_x11_event_translator_translate (event_translator, /*230*/
                                                   event_source->display,
                                                   xevent);
    }
  else
    {
      GList *list = event_source->translators;

      while (list && !event)
        {
          GdkEventTranslator *translator = list->data;

          list = list->next;
          event = _gdk_x11_event_translator_translate (translator,
                                                       event_source->display,
                                                       xevent);
        }
    }

  if (event &&
      (event->type == GDK_ENTER_NOTIFY ||
       event->type == GDK_LEAVE_NOTIFY) &&
      event->crossing.window != NULL)
    {
      /* Handle focusing (in the case where no window manager is running */
      handle_focus_change (&event->crossing);
    }

#ifdef HAVE_XGENERICEVENTS
  if (xevent->type == GenericEvent)
    XFreeEventData (dpy, &xevent->xcookie);
#endif

  return event;
}

>> #4  _gdk_x11_display_queue_events (display=0x55555645a0e0) at
>>../../../../../gdk/x11/gdkeventsource.c:341

void
_gdk_x11_display_queue_events (GdkDisplay *display)
{
  GdkEvent *event;
  XEvent xevent;
  Display *xdisplay = GDK_DISPLAY_XDISPLAY (display);
  GdkEventSource *event_source;
  GdkX11Display *display_x11;

  display_x11 = GDK_X11_DISPLAY (display);
  event_source = (GdkEventSource *) display_x11->event_source;

  while (!_gdk_event_queue_find_first (display) && XPending (xdisplay))
    {
      XNextEvent (xdisplay, &xevent);

      switch (xevent.type)
        {
        case KeyPress:
        case KeyRelease:
          break;
        default:
          if (XFilterEvent (&xevent, None))
            continue;
        }

      event = gdk_event_source_translate_event (event_source, &xevent); /*341*/

      if (event)
        {
          GList *node;

          node = _gdk_event_queue_append (display, event);
          _gdk_windowing_got_event (display, node, event, xevent.xany.serial);
        }
    }
}

>> #5  0x00007ffff75460e4 in gdk_display_get_event (display=display@entry=0x55555645a0e0)
>>     at ../../../../gdk/gdkdisplay.c:441

GdkEvent*
gdk_display_get_event (GdkDisplay *display)
{
  g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);

  if (display->event_pause_count == 0)
    GDK_DISPLAY_GET_CLASS (display)->queue_events (display); /*441*/

  return _gdk_event_unqueue (display);
}

>> #6  0x00007ffff757e0e6 in gdk_event_source_dispatch
>>     (source=<optimised out>, callback=<optimised out>, user_data=<optimised out>)
>>     at ../../../../../gdk/x11/gdkeventsource.c:363

static gboolean
gdk_event_source_dispatch (GSource     *source,
                           GSourceFunc  callback,
                           gpointer     user_data)
{
  GdkDisplay *display = ((GdkEventSource*) source)->display;
  GdkEvent *event;

  gdk_threads_enter ();

  event = gdk_display_get_event (display); /*363*/

  if (event)
    {
      _gdk_event_emit (event);

      gdk_event_free (event);
    }

  gdk_threads_leave ();

  return TRUE;
}

-- 
Dr Joseph A. Corneli (https://github.com/holtzermann17)

HYPERREAL ENTERPRISES LTD is a private company limited by shares, incorporated
25th, June 2019 as Company Number 634284 on the Register of Companies for
Scotland (https://beta.companieshouse.gov.uk/company/SC634284).