Подробности

[В начало]

Проблема в реализации № D0004

Краткое описание

Функция "g_main_context_check" игнорирует входной параметр "max_priority"

Подробное описание

Судя по документации параметр "max_priority" функции g_main_context_check задает: "the maximum numerical priority of sources to check". Это означает что все источники численным значением приоритета выше значения "max_priority" не подлежат проверке, в то время как в реализации данный параметр не оказывает никакого влияния на функциональность.

Раздел стандарта

Linux Standard Base Desktop Specification 3.1, Chapter 12. Libraries, 12.2 Interfaces for libglib-2.0; http://www.gtk.org/api/2.6/glib/glib-The-Main-Event-Loop.html#g-main-context-check

Способ воспроизведения

  1. К контексту подключаются 3 источника событий с численными значениями приоритетов {-1, 0, 1}
  2. Соответствующие функции источников заданы таким образом, что возвращают "FALSE" при вызовах "prepare*()" и "check*()"
  3. Проверяется чтобы возвращаемое значения после вызова "g_main_context_check()" было "FALSE"
  4. При правильном поведении единственным источником, проверенным после этого вызова должен был быть источник с численным значением приоритета равным "-1"
После запуска данного примера очевидно, что функция g_main_context_check производит проверку (вызов соответствующей функции "check*()") для всех трех источников событий, независимо от численного значения их приоритетов.

Пример

#include <unistd.h>
#include <stdio.h>
#include <glib.h>

int iter_CallbackCount = 0;
int iter_PrepareCount = 0;
int iter_CheckCount = 0;
int iter_DispatchCount = 0;
int iter_PollCount = 0;

gboolean iter_CallbackRetValue = FALSE;
gboolean iter_PrepareRetValue = FALSE;
gboolean iter_CheckRetValue = FALSE;
gint iter_Timeout = 0;

gboolean iter_callback(gpointer data)
{iter_CallbackCount++;return iter_CallbackRetValue;}
gboolean iter_prepare(GSource    *source, gint       *timeout_)
{iter_PrepareCount++;*timeout_=iter_Timeout;return iter_PrepareRetValue; }
gboolean iter_check(GSource    *source)
{iter_CheckCount++;return iter_CheckRetValue;}
gboolean iter_dispatch(GSource    *source, GSourceFunc callback,
                    gpointer user_data)
{iter_DispatchCount++;return callback(user_data);}


GSourceFuncs iter_funcs =
{
  iter_prepare,
  iter_check,
  iter_dispatch,
  NULL
};



int iter_init_sources(GMainContext* it_mainContext, GPollFD* fd_a,
            GSource** source_a, int pipe_a[3][2], gboolean eq_priority)
{
    for(int i = 0; i < 3; ++i)
    {

        if(pipe(pipe_a[i]) != 0)
        {
            return -1;
        }

        fd_a[i].fd = pipe_a[i][0];
        fd_a[i].events = G_IO_IN | G_IO_HUP | G_IO_ERR;
        fd_a[i].revents = 0;

        source_a[i] = g_source_new(&iter_funcs, sizeof (GSource));
        if(source_a[i] == NULL)
            return -2;
        g_source_set_callback (source_a[i], iter_callback, NULL, NULL);
        g_source_set_priority(source_a[i], eq_priority ?
                                G_PRIORITY_DEFAULT: i - 1);
        g_source_add_poll(source_a[i], &fd_a[i]);
        g_source_attach(source_a[i], it_mainContext);
        g_source_unref(source_a[i]);
    }
    return 0;
}


void iter_release_resources(GMainContext* it_mainContext, GSource** source_a,
                            int pipe_a[3][2])
{


    for(int i = 0; i < 3; ++i)
    {
        close(pipe_a[i][0]);
        close(pipe_a[i][1]);
    }

    if(it_mainContext){
        g_main_context_unref(it_mainContext);
    }

}


GMainContext *chk_mainContext;

int main()
{
    chk_mainContext = g_main_context_new();

    int pipe_a[3][2] = {{0}};
    GPollFD fd_a[3];

    GSource* source_a[3];

    iter_init_sources(chk_mainContext, fd_a, source_a, pipe_a, FALSE);

    GPollFD qfd_a[10];

    iter_PrepareCount = 0;
    iter_PrepareRetValue = FALSE;
    iter_Timeout = 8;
    int priority = 0;
    g_main_context_prepare (chk_mainContext, &priority);
    gint timeout;

    gint recordCount = g_main_context_query(chk_mainContext,
                                         2,
                                         &timeout,
                                         qfd_a,
                                         1);
    iter_CheckCount = 0;

    iter_CheckRetValue = FALSE;

    gint checkRetValue = g_main_context_check(chk_mainContext, -1, qfd_a,
                        recordCount);




    if(!(checkRetValue == FALSE && iter_CheckCount == 1))
    {
        char *message = checkRetValue == TRUE?
            "g_main_context_check: returned TRUE, although there is no source, "\
            "ready to be dispatched.\n"
            : "g_main_context_check: sources with higher numerical priority than"\
            "specified are being checked.\n";
    	printf(message);
    }

    iter_release_resources(chk_mainContext, source_a, pipe_a);

    return 0;
}

Компонент

gtk-glib 2.6.2 or later

Принято

Gnome Bugzilla 477659

[В начало]