Details

[Home]

Issue of the Implementation # D0006

Brief

Calling "g_main_context_pending" increases reference count for the ready sources

Detailed Description

Calling g_main_context_pending increases reference count for the ready sources, in the internal call to g_main_context_check. This function calls internal g_main_context_iterate, with "dispatch" parameter set to "FALSE". Normally, whenever g_main_context_iterate is called with "dispatch" parameter set to "TRUE", internal call of g_main_context_dispatch decreases the reference count of the dispatched sources.

Problem location(s) in the standard

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-pending

Reproducing

  1. 4 sources are attached to the newly created context, two of which with priority "-1" and two others with "1" and "2".
  2. First two sources will be marked as "READY" after internal call of "g_main_context_check" and reference count for them will be increased.
If "g_main_context_pending" would not have been called here, the following warnings would appear after the invocation of "g_main_context_unref" in the "for":
      (process:7320): GLib-WARNING **: gmain.c:1417: ref_count == 0, 
                           but source is still attached to a context!
     
      (process:7320): GLib-WARNING **: gmain.c:1417: ref_count == 0, 
                           but source is still attached to a context!
The absence of these warnings upon invocation of the sample shows that reference count for ready sources was increased during the call to "g_main_context_pending".

Example

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


int mci_CallbackCount = 0;
int mci_PrepareCount = 0;
int mci_CheckCount = 0;
int mci_DispatchCount = 0;
int mci_PollCount = 0;

gboolean mci_CallbackRetValue = FALSE;
gboolean mci_PrepareRetValue = FALSE;
gboolean mci_CheckRetValue = FALSE;

gint mci_Timeout = 0;

int mci_cb_status[4] = {0, 0, 0, 0};

gboolean mci_callback_P1(gpointer data)
    {mci_cb_status[0]++; return mci_CallbackRetValue;}
gboolean mci_callback_P2(gpointer data)
    {mci_cb_status[1]++; return mci_CallbackRetValue;}
gboolean mci_callback_P3(gpointer data)
    {mci_cb_status[2]++; return mci_CallbackRetValue;}
gboolean mci_callback_P4(gpointer data)
    {mci_cb_status[3]++; return mci_CallbackRetValue;}
gboolean (*mci_cbArray[4])(gpointer data) = 
    {mci_callback_P1, mci_callback_P2, mci_callback_P3, mci_callback_P4};



gboolean mci_prepare(GSource    *source, gint       *timeout_)
    {mci_PrepareCount++;*timeout_=mci_Timeout;return mci_PrepareRetValue; }
gboolean mci_check(GSource    *source)
    {mci_CheckCount++;return mci_CheckRetValue;}
gboolean mci_dispatch(GSource    *source, GSourceFunc callback, 
                                gpointer user_data)
    {mci_DispatchCount++;return callback(user_data);}


GSourceFuncs mci_funcs =
{
  mci_prepare,
  mci_check,
  mci_dispatch,
  NULL
};



int mci_status = 0;
GSource* mci_SourceArray[4] = {NULL, NULL, NULL, NULL};




int main()
{
    printf("Glib version %d.%d.%d \n\n", glib_major_version, glib_minor_version,
                    glib_micro_version );

    mci_Timeout = -1;

    mci_status = 0;
    mci_CallbackRetValue = TRUE;
    mci_PrepareRetValue = FALSE;
    mci_CheckRetValue = TRUE;

    GMainContext *mcp_MainContext =  g_main_context_new();


    for(int i = 0; i < 4; ++i)
    {

        GSource *mci_source = (GSource*)g_source_new(&mci_funcs, 
                                                sizeof (GSource));
        mci_SourceArray[i] = mci_source;
        g_source_set_callback (mci_source, mci_cbArray[i], NULL, NULL);
        g_source_set_priority(mci_source, i < 2 ? -1 : i - 1);
        g_source_attach(mci_source, mcp_MainContext);
        g_source_unref(mci_source);
    }

   	g_main_context_pending(mcp_MainContext);

    /*
     * if g_main_context_pending() would not have called here, after the
     * following lines "g_main_context_unref()" would give 2 warning like:
     *
     * --------
     * (process:7320): GLib-WARNING **: gmain.c:1417: ref_count == 0, 
     *                      but source is still attached to a context!
     *
     * (process:7320): GLib-WARNING **: gmain.c:1417: ref_count == 0, 
     *                      but source is still attached to a context!
     * --------
     *
     * which means that reference count for ready sources was increased upon
     * calling "g_main_context_pending()".
     *
     *
     */

    for(int i = 0; i < 2; ++i)
    {
        g_source_unref(mci_SourceArray[i]);
    }

    if(mcp_MainContext)
       g_main_context_unref(mcp_MainContext);


    return 0;
}

Component

gtk-glib 2.6.2 or later

Accepted

Gnome Bugzilla 479787

[Home]