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 614650 - GStreamer crash when using playbin2 and about_to_finish signal
GStreamer crash when using playbin2 and about_to_finish signal
Status: RESOLVED FIXED
Product: gnome-perl
Classification: Bindings
Component: GStreamer
unspecified
Other Linux
: Normal normal
: ---
Assigned To: gtk2-perl-bugs
gtk2-perl-bugs
Depends on: 620099
Blocks:
 
 
Reported: 2010-04-02 10:22 UTC by Quentin Sculo
Modified: 2012-02-19 15:54 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
test case (1.61 KB, application/x-perl)
2010-04-02 10:22 UTC, Quentin Sculo
  Details
Fix a threading bug in dGPERL_CLOSURE_MARSHAL_ARGS (2.00 KB, patch)
2010-04-16 22:52 UTC, Torsten Schoenfeld
none Details | Review
a few examples of backtraces (29.19 KB, text/plain)
2010-04-24 23:06 UTC, Quentin Sculo
  Details
valgrind output (41.71 KB, text/plain)
2010-04-24 23:11 UTC, Quentin Sculo
  Details

Description Quentin Sculo 2010-04-02 10:22:13 UTC
Created attachment 157742 [details]
test case

When using the about_to_finish signal of playbin2, the program randomly crash if it is busy (ie: a few seconds without running the mainloop) when the about_to_finish signal is fired by gstreamer.

I could reproduce the problem in the attached test case, give it 2 files as arguments, it will skip toward the end of the first one, and then count to a very high number to make it busy.
Most of the time, the program will randomly crash when the about_to_finish signal is fired.
When it does not crash, you can see that the "about to finish" message is printed while the program was counting to a high number, which means the perl callback was called from a gstreamer thread.
Comment 1 Torsten Schoenfeld 2010-04-16 22:52:52 UTC
Created attachment 158929 [details] [review]
Fix a threading bug in dGPERL_CLOSURE_MARSHAL_ARGS

Previously, dGPERL_CLOSURE_MARSHAL_ARGS used the dSP macro to declare
the stack pointer.  But dSP involves accessing the my_perl pointer which
might be invalid if we've been called from a thread other than the main
one.  To avoid this, manually declare SV **sp first and let
GPERL_CLOSURE_MARSHAL_INIT initialize it after it has set up my_perl via
PERL_SET_CONTEXT.

This fixes the bug with your example program on my system.  Quentin, can you
verify this?
Comment 2 Quentin Sculo 2010-04-18 16:00:35 UTC
Sadly, it still crashes for me. Both with the test-case and in my program.

I tested it with the perl from mandriva 2010 : perl-5.10.1 (Compile-time options: MULTIPLICITY PERL_DONT_CREATE_GVSV PERL_IMPLICIT_CONTEXT PERL_MALLOC_WRAP USE_ITHREADS USE_LARGE_FILES USE_PERLIO USE_REENTRANT_API)

and with a brand new perl-5.12.0 (Compile-time options: PERL_DONT_CREATE_GVSV PERL_MALLOC_WRAP USE_LARGE_FILES USE_PERLIO USE_PERL_ATOF)
Comment 3 Torsten Schoenfeld 2010-04-24 21:07:25 UTC
How does it crash exactly, i.e. what do gdb and valgrind say?

  $ gdb perl
  > r test.pl
  ... segfault ...
  > bt

  $ valgrind --tool=memcheck --num-callers=50 perl test.pl
Comment 4 Quentin Sculo 2010-04-24 23:06:15 UTC
Created attachment 159490 [details]
a few examples of backtraces

made with the patch above (Fix a threading bug in dGPERL_CLOSURE_MARSHAL_ARGS)
it crashes ~50 % of the times
Comment 5 Quentin Sculo 2010-04-24 23:11:54 UTC
Created attachment 159491 [details]
valgrind output

output of "valgrind --tool=memcheck --num-callers=50"
(also made with the patch)
I added the output of a case where it did not crash, for comparison.
Comment 6 Torsten Schoenfeld 2010-05-30 15:24:34 UTC
OK, this turned out to be way more intricate than expected.  Basically, the problem is, as I'm sure you know already, that the about_to_finish signal handler is called from a new thread.  And we're not prepared to handle this.  See bug 620099 for my current stab at this.

If you want to test this, make sure you pass the callback reference by name, like this:

  $player->signal_connect(about_to_finish => "main::about_to_finish", $file2);

Passing code references (i.e., \&about_to_finish) between threads is not supported (by us, but also by perl).
Comment 7 muppet 2010-06-01 03:17:21 UTC
As an experiment, can you try having the callback call g_idle_add() to defer execution of the callback action to the main loop?

The simple approach would be

   sub about_to_finish
   {
           Glib::Idle->add (sub { ...});
   }

but i suspect that will crash for the same reasons.

So, you might actually want to use a C/XS thunk to experiment.  For example:

    $player->signal_connect (about_to_finish => 'thunk_to_mainloop', $file2);

where 'thunk_to_mainloop' is the name of an XSub that calls g_idle_add() under the hook to ask the main loop to invoke a function.

This way you get the code executed on a thread that we do know about.
Comment 8 Torsten Schoenfeld 2011-05-15 16:02:28 UTC
I've now implemented muppet's suggestion in attachment 187851 [details] [review] to bug 620099.  It sort of fixes the problem.  "Sort of" because it does not fix the test case as-is.  The timeout source \&count needs to be disabled (or, at least, its duration needs to be shortened) for the new approach to work: with it still in place, the main loop is blocked from processing the about-to-finish invocation in time.

Is that still good enough for your purposes, Quentin?