After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 554887 - boxed type registration is not thread safe
boxed type registration is not thread safe
Status: RESOLVED FIXED
Product: glib
Classification: Platform
Component: gobject
2.23.x
Other Linux
: Normal critical
: ---
Assigned To: gtkdev
gtkdev
: 555103 561980 576857 579035 583962 593398 594847 (view as bug list)
Depends on:
Blocks:
 
 
Reported: 2008-10-03 16:34 UTC by Pedro Villavicencio
Modified: 2010-01-25 14:34 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
Test case (931 bytes, text/plain)
2009-09-23 10:42 UTC, Alberto Garcia
  Details
Patch (4.01 KB, patch)
2009-09-23 10:44 UTC, Alberto Garcia
none Details | Review
Updated patch (5.90 KB, patch)
2009-09-23 14:24 UTC, Alberto Garcia
none Details | Review
Put calls to registered copy/free functions into separate functions (6.14 KB, patch)
2010-01-20 21:27 UTC, Benjamin Otte (Company)
committed Details | Review
Move the boxed private type data to TypeNode (9.40 KB, patch)
2010-01-20 21:27 UTC, Benjamin Otte (Company)
committed Details | Review

Description Pedro Villavicencio 2008-10-03 16:34:44 UTC
this report has been filed here:

https://bugs.edge.launchpad.net/ubuntu/+source/rhythmbox/+bug/277299

"After starting Rhythmbox I tried to start playing an MP3-stream (internet radio). Rhythmbox froze for a few seconds before closing and apport reported an error."

rhythmbox version is: 0.11.6svn20080916

".

Thread 3 (process 9832)

  • #0 free
    from /lib/libc.so.6
  • #1 IA__g_signal_newv
    at /build/buildd/glib2.0-2.18.1/gobject/gsignal.c line 351
  • #2 IA__g_signal_new_valist
    at /build/buildd/glib2.0-2.18.1/gobject/gsignal.c line 1687
  • #3 IA__g_signal_new
    at /build/buildd/glib2.0-2.18.1/gobject/gsignal.c line 1329
  • #4 totem_pl_parser_class_init
    at totem-pl-parser.c line 372
  • #5 IA__g_type_class_ref
    at /build/buildd/glib2.0-2.18.1/gobject/gtype.c line 1989
  • #6 IA__g_object_newv
    at /build/buildd/glib2.0-2.18.1/gobject/gobject.c line 1127
  • #7 IA__g_object_new_valist
    at /build/buildd/glib2.0-2.18.1/gobject/gobject.c line 1274
  • #8 IA__g_object_new
    at /build/buildd/glib2.0-2.18.1/gobject/gobject.c line 1056
  • #9 totem_pl_parser_new
    at totem-pl-parser.c line 617
  • #10 open_location_thread
    at rb-shell-player.c line 1516
  • #11 g_thread_create_proxy
    at /build/buildd/glib2.0-2.18.1/glib/gthread.c line 635
  • #12 start_thread
    from /lib/libpthread.so.0
  • #13 clone
    from /lib/libc.so.6
  • #14 ??

Thread 1 (process 9818)

  • #0 boxed_nodes_cmp
    at /build/buildd/glib2.0-2.18.1/gobject/gboxed.c line 79
  • #1 boxed_proxy_lcopy_value
    at /build/buildd/glib2.0-2.18.1/glib/gbsearcharray.h line 163
  • #2 IA__g_object_get_valist
    at /build/buildd/glib2.0-2.18.1/gobject/gobject.c line 1496
  • #3 IA__g_object_get
    at /build/buildd/glib2.0-2.18.1/gobject/gobject.c line 1584
  • #4 check_entry_type
    at rb-streaming-source.c line 246
  • #5 streaming_artist_request_cb
    at rb-streaming-source.c line 279
  • #6 rb_marshal_BOXED__BOXED
    at rb-marshal.c line 595
  • #7 IA__g_closure_invoke
    at /build/buildd/glib2.0-2.18.1/gobject/gclosure.c line 767
  • #8 signal_emit_unlocked_R
    at /build/buildd/glib2.0-2.18.1/gobject/gsignal.c line 3244
  • #9 IA__g_signal_emit_valist
    at /build/buildd/glib2.0-2.18.1/gobject/gsignal.c line 2987
  • #10 IA__g_signal_emit
    at /build/buildd/glib2.0-2.18.1/gobject/gsignal.c line 3034
  • #11 rhythmdb_entry_request_extra_metadata
    at rhythmdb.c line 4099
  • #12 rb_shell_construct_notify_titles
    at rb-shell.c line 2998
  • #13 rb_shell_player_window_title_changed_cb
    at rb-shell.c line 2087
  • #14 IA__g_closure_invoke
    at /build/buildd/glib2.0-2.18.1/gobject/gclosure.c line 767
  • #15 signal_emit_unlocked_R
    at /build/buildd/glib2.0-2.18.1/gobject/gsignal.c line 3244
  • #16 IA__g_signal_emit_valist
    at /build/buildd/glib2.0-2.18.1/gobject/gsignal.c line 2977
  • #17 IA__g_signal_emit
    at /build/buildd/glib2.0-2.18.1/gobject/gsignal.c line 3034
  • #18 rb_shell_player_sync_with_source
    at rb-shell-player.c line 2993
  • #19 rb_shell_player_playpause
    at rb-shell-player.c line 2437
  • #20 rb_shell_player_cmd_play
    at rb-shell-player.c line 2308
  • #21 IA__g_closure_invoke
    at /build/buildd/glib2.0-2.18.1/gobject/gclosure.c line 767
  • #22 signal_emit_unlocked_R
    at /build/buildd/glib2.0-2.18.1/gobject/gsignal.c line 3244
  • #23 IA__g_signal_emit_valist
    at /build/buildd/glib2.0-2.18.1/gobject/gsignal.c line 2977
  • #24 IA__g_signal_emit
    at /build/buildd/glib2.0-2.18.1/gobject/gsignal.c line 3034
  • #25 _gtk_action_emit_activate
    at /build/buildd/gtk+2.0-2.14.3/gtk/gtkaction.c line 885
  • #26 IA__g_closure_invoke
    at /build/buildd/glib2.0-2.18.1/gobject/gclosure.c line 767
  • #27 signal_emit_unlocked_R
    at /build/buildd/glib2.0-2.18.1/gobject/gsignal.c line 3244
  • #28 IA__g_signal_emit_valist
    at /build/buildd/glib2.0-2.18.1/gobject/gsignal.c line 2977
  • #29 IA__g_signal_emit_by_name
    at /build/buildd/glib2.0-2.18.1/gobject/gsignal.c line 3071
  • #30 IA__g_closure_invoke
    at /build/buildd/glib2.0-2.18.1/gobject/gclosure.c line 767
  • #31 signal_emit_unlocked_R
    at /build/buildd/glib2.0-2.18.1/gobject/gsignal.c line 3244
  • #32 IA__g_signal_emit_valist
    at /build/buildd/glib2.0-2.18.1/gobject/gsignal.c line 2977
  • #33 IA__g_signal_emit
    at /build/buildd/glib2.0-2.18.1/gobject/gsignal.c line 3034
  • #34 gtk_toggle_button_released
    at /build/buildd/gtk+2.0-2.14.3/gtk/gtktogglebutton.c line 426
  • #35 IA__g_closure_invoke
    at /build/buildd/glib2.0-2.18.1/gobject/gclosure.c line 767
  • #36 signal_emit_unlocked_R
    at /build/buildd/glib2.0-2.18.1/gobject/gsignal.c line 3174
  • #37 IA__g_signal_emit_valist
    at /build/buildd/glib2.0-2.18.1/gobject/gsignal.c line 2977
  • #38 IA__g_signal_emit
    at /build/buildd/glib2.0-2.18.1/gobject/gsignal.c line 3034
  • #39 gtk_button_button_release
    at /build/buildd/gtk+2.0-2.14.3/gtk/gtkbutton.c line 1383
  • #40 _gtk_marshal_BOOLEAN__BOXED
    at /build/buildd/gtk+2.0-2.14.3/gtk/gtkmarshalers.c line 84
  • #41 IA__g_closure_invoke
    at /build/buildd/glib2.0-2.18.1/gobject/gclosure.c line 767
  • #42 signal_emit_unlocked_R
    at /build/buildd/glib2.0-2.18.1/gobject/gsignal.c line 3282
  • #43 IA__g_signal_emit_valist
    at /build/buildd/glib2.0-2.18.1/gobject/gsignal.c line 2987
  • #44 IA__g_signal_emit
    at /build/buildd/glib2.0-2.18.1/gobject/gsignal.c line 3034
  • #45 gtk_widget_event_internal
    at /build/buildd/gtk+2.0-2.14.3/gtk/gtkwidget.c line 4745
  • #46 IA__gtk_propagate_event
    at /build/buildd/gtk+2.0-2.14.3/gtk/gtkmain.c line 2391
  • #47 IA__gtk_main_do_event
    at /build/buildd/gtk+2.0-2.14.3/gtk/gtkmain.c line 1596
  • #48 gdk_event_dispatch
    at /build/buildd/gtk+2.0-2.14.3/gdk/x11/gdkevents-x11.c line 2365
  • #49 IA__g_main_context_dispatch
    at /build/buildd/glib2.0-2.18.1/glib/gmain.c line 2142
  • #50 g_main_context_iterate
    at /build/buildd/glib2.0-2.18.1/glib/gmain.c line 2776
  • #51 IA__g_main_loop_run
    at /build/buildd/glib2.0-2.18.1/glib/gmain.c line 2984
  • #52 IA__gtk_main
    at /build/buildd/gtk+2.0-2.14.3/gtk/gtkmain.c line 1200
  • #53 main
    at main.c line 330

Thanks!,
Comment 1 Jonathan Matthew 2008-11-23 07:37:51 UTC
*** Bug 561980 has been marked as a duplicate of this bug. ***
Comment 2 Jonathan Matthew 2008-11-23 10:28:08 UTC
What's happening here is that a new boxed type is being registered (in totem_pl_parser_class_init) while a boxed value is being used elsewhere (the g_object_get in check_entry_type is retrieving a boxed value).

Registered boxed types are stored in a binary search array.  With nothing protecting against concurrent reads and writes to the array, it's going to crash sometimes.
Comment 3 Tim Janik 2008-12-01 18:26:13 UTC
(In reply to comment #2)
> What's happening here is that a new boxed type is being registered (in
> totem_pl_parser_class_init) while a boxed value is being used elsewhere (the
> g_object_get in check_entry_type is retrieving a boxed value).

Right, thanks for figuring. What's needed is locking a mutex around accesses to gboxed.c:boxed_bsa.
Comment 4 Jonathan Matthew 2009-03-26 23:30:10 UTC
*** Bug 576857 has been marked as a duplicate of this bug. ***
Comment 5 Jonathan Matthew 2009-04-15 11:25:13 UTC
*** Bug 579035 has been marked as a duplicate of this bug. ***
Comment 6 Jonathan Matthew 2009-05-28 00:16:12 UTC
*** Bug 583962 has been marked as a duplicate of this bug. ***
Comment 7 Jonathan Matthew 2009-08-28 22:48:37 UTC
*** Bug 593398 has been marked as a duplicate of this bug. ***
Comment 8 Jonathan Matthew 2009-09-11 23:21:29 UTC
*** Bug 594847 has been marked as a duplicate of this bug. ***
Comment 9 Alberto Garcia 2009-09-23 10:42:33 UTC
Created attachment 143778 [details]
Test case

Here's a test case. Compile and run with

 $ while true; do ./test ; done

and you'll see core dumps galore.
Comment 10 Alberto Garcia 2009-09-23 10:44:22 UTC
Created attachment 143779 [details] [review]
Patch

And here's a patch to fix the problem
Comment 11 Alberto Garcia 2009-09-23 14:24:31 UTC
Created attachment 143800 [details] [review]
Updated patch

There's a problem with the previous patch, and it's that if
node->copy() or node->free() make calls to GBoxed functions it'll
block the program since the mutex would be locked.

This patch fixes that problem.
Comment 12 Alberto Garcia 2009-09-28 00:05:07 UTC
can please someone review this patch and commit? thanks !
Comment 13 Alberto Garcia 2010-01-20 17:10:47 UTC
ping
Comment 14 Javier Jardón (IRC: jjardon) 2010-01-20 17:32:00 UTC
*** Bug 555103 has been marked as a duplicate of this bug. ***
Comment 15 Matthias Clasen 2010-01-20 17:44:12 UTC
I think this might be a great case for GAtomicArray.
Comment 16 Benjamin Otte (Company) 2010-01-20 21:27:45 UTC
Created attachment 151870 [details] [review]
Put calls to registered copy/free functions into separate functions

This eases cleaning up these functions.

One optimization in value_set_internal() was lost in the process. It
shouldn't cause too many issues when all is said and done.
Comment 17 Benjamin Otte (Company) 2010-01-20 21:27:51 UTC
Created attachment 151871 [details] [review]
Move the boxed private type data to TypeNode

This way we don't need to keep a custom array that we bsearch on (and
that isn't threadsafe) but can use the gtype.c machinery that is
threadsafe. And fast, too!
Comment 18 Benjamin Otte (Company) 2010-01-20 21:31:38 UTC
Here's an implementation that uses the TypeNode data available in gtype.c and therefor does not require its own lock for every copy/free.
It passes the attached test (it's running in the background as I type this and hasn't complained yet). It should be faster, too because it avoids the bsearch.

The only thing I don't like is the interaction with gtype.c and the necessity to introduce gtype-private.h. But I think it's the best solution.
Comments?
Comment 19 Matthias Clasen 2010-01-22 17:48:49 UTC
Looks reasonable to me.
Comment 20 Alexander Larsson 2010-01-25 14:28:56 UTC
looks ok to me too