[webkit-gtk] What supposed to hold the GDK in calls from WebKit/gtk/WebCoreSupport

Yehouda Harpaz yeh at lispworks.com
Mon Aug 22 06:15:07 PDT 2011


>  
>  On Sun, 2011-08-21 at 11:50 +0100, Yehouda Harpaz wrote:
>  > Maybe it is assumed that there will a lock around, but I don't see
>  > where. Since it is called from Soup code that is itself called from
>  > g_main_dispatch, there cannot be a lock at that point. And I don't
>  > anyting inside that tries to look.
>  
>  So, if the code is being called from the main loop it should be properly
>  locked. You are probably missing a pair of threads_enter/threads_leave
>  around gtk_main(). From the blog post:
>  
>  "It turns out that you’re supposed to put gdk_threads_enter()/leave()
>  around the call you make to gtk_main(). I suppose that this is implicit
>  in the injunction to protect all GTK calls, but I know I’m not the only
>  one to have had the impression that the main loop was special somehow.
>  It certainly isn’t explicit on the GDK threads API page, and although it
>  turns up (sort of) in the code examples there, the number of people that
>  get this wrong is staggering. So I think we’ll need to improve that
>  documentation a bit."
>  
>  I assume you missed that bit? 


No, I didn't.
gtk_main releases the lock before calling  g_main_loop_run (see code
below), so a lock around it will not help. 

The locking in GTK and GDK occurs because GDK adds its own GSources,
and the dispatchs for them (gdk_threads_enter for timeouts and idles
and gdk_event_dispatch for events on X11, code below) lock around
executing the actual func.


> If you are doing that and it's not working
>  we'll have to dive a bit more, a bug report would be a good way to go
>  forward I'd say.

Probably. I was hoping somebody on this list knows the answer. 


//-------------------------- 
//-------------------------- 
//-------------------------- 


void
gtk_main (void)
{
  GList *tmp_list;
  GList *functions;
  GtkInitFunction *init;
  GMainLoop *loop;

  gtk_main_loop_level++;
  
  loop = g_main_loop_new (NULL, TRUE);
  main_loops = g_slist_prepend (main_loops, loop);

  tmp_list = functions = init_functions;
  init_functions = NULL;
  
  while (tmp_list)
    {
      init = tmp_list->data;
      tmp_list = tmp_list->next;
      
      (* init->function) (init->data);
      g_free (init);
    }
  g_list_free (functions);

  if (g_main_loop_is_running (main_loops->data))
    {
      GDK_THREADS_LEAVE ();
      g_main_loop_run (loop);
      GDK_THREADS_ENTER ();
      gdk_flush ();
    }

  if (quit_functions)
    {
      GList *reinvoke_list = NULL;
      GtkQuitFunction *quitf;

      while (quit_functions)
	{
	  quitf = quit_functions->data;

	  tmp_list = quit_functions;
	  quit_functions = g_list_remove_link (quit_functions, quit_functions);
	  g_list_free_1 (tmp_list);

	  if ((quitf->main_level && quitf->main_level != gtk_main_loop_level) ||
	      gtk_quit_invoke_function (quitf))
	    {
	      reinvoke_list = g_list_prepend (reinvoke_list, quitf);
	    }
	  else
	    {
	      gtk_quit_destroy (quitf);
	    }
	}
      if (reinvoke_list)
	{
	  GList *work;
	  
	  work = g_list_last (reinvoke_list);
	  if (quit_functions)
	    quit_functions->prev = work;
	  work->next = quit_functions;
	  quit_functions = work;
	}

      gdk_flush ();
    }
    
  main_loops = g_slist_remove (main_loops, loop);

  g_main_loop_unref (loop);

  gtk_main_loop_level--;

  if (gtk_main_loop_level == 0)
    {
      /* Try storing all clipboard data we have */
      _gtk_clipboard_store_all ();

      /* Synchronize the recent manager singleton */
      _gtk_recent_manager_sync ();
    }
}










///----------------------------------------

static gboolean
gdk_threads_dispatch (gpointer data)
{
  GdkThreadsDispatch *dispatch = data;
  gboolean ret = FALSE;

  GDK_THREADS_ENTER ();

  if (!g_source_is_destroyed (g_main_current_source ()))
    ret = dispatch->func (dispatch->data);

  GDK_THREADS_LEAVE ();

  return ret;
}


///----------------------------------------

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

  _gdk_events_queue (display);
  event = _gdk_event_unqueue (display);

  if (event)
    {
      if (_gdk_event_func)
	(*_gdk_event_func) (event, _gdk_event_data);
      
      gdk_event_free (event);
    }
  
  GDK_THREADS_LEAVE ();

  return TRUE;
}



More information about the webkit-gtk mailing list