Uploaded image for project: 'Qt'
  1. Qt
  2. QTBUG-48344

QEventDispatcherGlib: timers don't timeout due to higher priority of socket notifier event dispatching

    XMLWordPrintable

Details

    • Bug
    • Resolution: Done
    • P2: Important
    • 5.11.2
    • 5.3.2, 5.5.0
    • None
    • Linux; CentOS 6.5 / CentOS 6.6
    • 6854fa75f7

    Description

      As posted on the mailing list, there seems to be a possible issue with the Glib event dispatcher:

      I'm running into an issue where it seems that Qt timers are not timing
      out anymore when the application has a lot of other events (say
      continues stream of events) to process. For instance, when the
      application receives lots of small pieces of data on (TCP) sockets,
      resulting in a lot of events to be dispatched.

      This applies to Qt on linux. It is a situation difficult to reproduce,
      but is more or less reproducible by creating a "receiver" application
      using QSocketNotifier directly or using a QTcpSocket in buffered state
      or buffer size of 1. Next create a sender application that produces a
      continues stream of small pieces of data. I can provide a reproducible
      case if needed.

      But first, this seems to be related to the fact that
      QEventDispatcherGlib implements two timer sources for the glib event
      loop processing (see its constructor):

      1. Event dispatching with default priority, which is prioritized
        equally to other events, like socket notifier events.
      2. Event dispatching with 'idle' priority, which is a lower priority
        than the default priority. The dispatching of these events only occurs
        when the application is 'idle'. ( see the use of
        g_source_set_priority(<source>, G_PRIORITY_DEFAULT_IDLE) )

      The second case seems to be applicable to all timers in general, when
      the application's event loop is running. This means that as long as
      there are other events than timer events to be dispatched, The timers
      do not run out.

      What is interesting is that this behavior does not occur when
      switching to QEventDispatcherUnix (using the environment variable
      QT_NO_GLIB=1). With the unix event dispatcher, the timers keep running
      out as the event dispatching seem to be prioritized equally to other
      type of events. Even without much of a delay, although the rate of
      incoming data pieces is relatively high.

      The behavior of the UNIX event dispatcher feels more reasonable,
      because it ensures that all timer events will be triggered and get
      there processing time without unnecessary delay.

      However it looks like the 'idle' priority was implemented for a
      reason. But considering the side effects described above, it doesn't
      seem to work as expected.

      Can someone advise whether this is the behavior as intended or whether
      this points to an issue in Qt?

      (Source: http://lists.qt-project.org/pipermail/interest/2015-September/018810.html)

      And the follow-up:

      > From the description of the symptom and from the fact that the non-glib
      > dispatcher behaves differently, it sounds like this behaviour is not intended.
      >
      > I'll ask you to file a bug about this. Unfortunately, I can tell you the bug
      > will get assigned to me and I have little clue about the workings of the Glib
      > dispatcher and I don't know how to fix the issue. Help would be appreciated
      > (maybe I'll ask on Google+ if someone who knows glib can advise).

      Thanks, I will gather as much detailed information as I can and create
      a bug report with it.

      One thing that I did find out is that the problem does not occur when
      I apply the following patch to the GLIB event dispatcher in Qt:

      --- ORG/qtbase/src/corelib/kernel/qeventdispatcher_glib.cpp
      2015-09-17 16:13:14.726026280 +0200
      +++ TEST/qtbase/src/corelib/kernel/qeventdispatcher_glib.cpp
      2015-09-17 15:19:27.391698360 +0200
      @@ -370,7 +339,7 @@ QEventDispatcherGlibPrivate::QEventDispa
      
        sizeof(GIdleTimerSource)));
           idleTimerSource->timerSource = timerSource;
           g_source_set_can_recurse(&idleTimerSource->source, true);
      -    g_source_set_priority(&idleTimerSource->source, G_PRIORITY_DEFAULT_IDLE);
      +//    g_source_set_priority(&idleTimerSource->source, G_PRIORITY_DEFAULT_IDLE);
           g_source_attach(&idleTimerSource->source, mainContext);
       }
      
      

      With this patch the timer event dispatching occurs with the same
      priority as other type of events and the GLIB dispatcher seemingly
      behaves the same as the UNIX dispatcher.

      However I'm no expert at this point and this will probably have
      unexpected side effects. Moreover, it makes the whole implementation
      of the explicit difference between idle and non-idle event dispatching
      in the GLIB dispatcher useless.

      I'm not sure if this information helps, but please let me know if
      there is anything more that I can do that will help.

      (Source: http://lists.qt-project.org/pipermail/interest/2015-September/018846.html)

      Attached are small c++ source files for two test application, the 'sender' application and 'receiver' application that are described in the quotes above.

      Attachments

        1. receivermain.cpp
          1 kB
          Danny Smit
        2. receivermain.h
          0.2 kB
          Danny Smit
        3. sendermain.cpp
          0.6 kB
          Danny Smit
        No reviews matched the request. Check your Options in the drop-down menu of this sections header.

        Activity

          People

            svuorela Sune Vuorela
            smit Danny Smit
            Votes:
            2 Vote for this issue
            Watchers:
            6 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved:

              Gerrit Reviews

                There are no open Gerrit changes