threaded version of load_images_to_ram segfaults

Bug #733579 reported by Marco Lazzaroni
6
This bug affects 1 person
Affects Status Importance Assigned to Milestone
Luce Image Viewer
Fix Released
Critical
Unassigned

Bug Description

..while calling clutter_texture_set_from_rgb_data().

Tags: segfault

Related branches

Changed in luce:
status: New → Confirmed
importance: Undecided → Critical
milestone: none → 0.0.3
tags: added: segfault
Revision history for this message
Marco Lazzaroni (marcolazzaroni) wrote :

it's quite strange. I set to run load_images_to_ram to a separate thread.
luce crashes inside clutter_texture_set_from_rgb_data() (it should at least return an error...)
if i call load_images_to_ram in the same thread, everything is ok
either I don't correctly setup the thread or ... i don't know

Revision history for this message
Marco Lazzaroni (marcolazzaroni) wrote :

see http://stackoverflow.com/questions/3831767/c-clutter-1-0-calling-function-from-thread-causes-segfault

The bug is not solved yet. I have to find a smart way to accomplish it, too.
Clutter function must be called from the same thread that called clutter_init and clutter main: I have to think about it.

Revision history for this message
Marco Lazzaroni (marcolazzaroni) wrote :

I have to decide whether it's better to call clutter_texture_set_from_rgb_data() in a "deterministic" way or waiting idle cycles of the clutter thread.

Revision history for this message
Sergey "Shnatsel" Davidoff (shnatsel) wrote :

I'm smoking threading manuals for a better solution, no results yet.

Revision history for this message
Sergey "Shnatsel" Davidoff (shnatsel) wrote :

I've noticed that _REENTRANT macro, required for safe threading (as my book says, it describes pthread in NTPL implementation). Is that OK?

Revision history for this message
Sergey "Shnatsel" Davidoff (shnatsel) wrote :

I meant that the book descibes pthread in NTPL implementation, and the macro is needed for replacing functions with reentrant equivalents (notably stdio buffered I/O), making errno variable thread-local and so on.

Revision history for this message
Sergey "Shnatsel" Davidoff (shnatsel) wrote :

And that phrase is incomplete anyway... I've noticed that the macro _REENTRANT is not declared. Is this OK?

This issue doesn't seem to be a problem when using pthread library, it has awesome pthread_exit() and pthread_join(). Just load the RGB data in a thread, and wait till the RGB-loading thread does its job in the clutter-calling thread with pthread_join(), which doesn't seem to waste CPU cycles.

See also: http://stackoverflow.com/questions/2156353/how-do-you-query-a-pthread-to-see-if-it-is-still-running

Revision history for this message
Sergey "Shnatsel" Davidoff (shnatsel) wrote :

g_thread_join() is the glib equivalent to pthread_join(). Will smoke some Luce code now, but (as you can see) my brainpower is low atm.

Revision history for this message
Marco Lazzaroni (marcolazzaroni) wrote :

If I get it right, I think that any consideration involves modifying clutter source, which is not a workable solution.

As stated in http://docs.clutter-project.org/docs/clutter/stable/clutter-General.html "The only safe and portable way to use the Clutter API in a multi-threaded environment is to never access the API from a thread that did not call clutter_init() and clutter_main()."

At the moment che source code of luce does NOT follow this rule.

Also, the following scheme is mandatory in a multi thread environment (and already implemented in luce):

int
main (int argc, char *argv[])
{
  /* initialize GLib's threading support */
  g_thread_init (NULL);

  /* initialize Clutter's threading support */
  clutter_threads_init ();

  /* initialize Clutter */
  clutter_init (&argc, &argv);

  /* program code */

  /* acquire the main lock */
  clutter_threads_enter ();

  /* start the main loop */
  clutter_main ();

  /* release the main lock */
  clutter_threads_leave ();

  /* clean up */
  return 0;
}

Also, "The common pattern for using threads with Clutter is to use worker threads to perform blocking operations and then install idle or timeour sources with the result when the thread finished.".

So my choice is either A) use idle time of the thread that called clutter_init by use of clutter_threads_add_idle() or B) insert the calls I need between clutter_init and clutter_main

Solution B) is good for everything that can be done in the inizialisation phase. Since I want to postpone some work after the inizialisation, the only workable solution is A).
I need some synchronization; I think I can get it with a semaphore, a token, or something similar.

Revision history for this message
Marco Lazzaroni (marcolazzaroni) wrote :

I have to try adding clutter_threads_enter / leave () around the clutter_* call in call_clutter_texture_set_from_rgb_data

Revision history for this message
Marco Lazzaroni (marcolazzaroni) wrote :

fixed by release 47. Now the texture realization is postponed to the moment of the refresh, while the loading is done in a separate thread at the beginning.

Changed in luce:
status: Confirmed → Fix Committed
Revision history for this message
Marco Lazzaroni (marcolazzaroni) wrote :

I have addressed the problem with some mutexes. It barely works now :-)

Changed in luce:
status: Fix Committed → Fix Released
To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.