Killing Zombies - Unref-ing pipelines waiting for async change

classic Classic list List threaded Threaded
11 messages Options
Reply | Threaded
Open this post in threaded view
|

Killing Zombies - Unref-ing pipelines waiting for async change

Wes Miller
Administrator
Hi All,

I have a program with a receiver pipeline (essentially, udpsrc->decodebin->autoaudiosinkl) that may or may not do any receiving depending on if another program connects to it.  The pipe is set up and gets to the point in the code where it is "hung" in async state waiting on the external connection to send in some data.

Later on when it's time to shut the program down, I send an EOS to the "hung" receiver pipe, but since the pipeline is not complete and, therefore, not moving data down the pipe, the EOS has no effect.

So, what's the best way to handle this? I am sure there has to be a better way than what I've considered:

1. Use a separate variable that is true only if the pipe is in "Running" state and use that var to just not bother with the EOS.  If I do that, what do I need to do besides unref the pipeline?  Will it unref while it is in "async" state?  Can I move it to some other state, like "NULL" and then deref it?

2.  Get the state of the pipe and just deref it if the state is async?  Can I ask the same pipe for its state twice, i.e. will the gst_element_get_state() functions collide?  Interfere with each other?  Crash?

3. Hold off on linking the pads in the New-Decoded-Pad signal callback and wait for a signal from udpsrc to say it has data before linking?  Would this make it easier to move the pipeline back to "NULL" state?

4. Use a split src consisting of the udpsrc and a audiotestsrc connected to a selector and send myself a burst of data to prime the pipe then change inputs to the udssrc?  This one is going to require an example pipe spec.

5. Is there an "interrupt state change" mechanism for the pipeline?

Thanks for any help.

Wes


Reply | Threaded
Open this post in threaded view
|

Re: Killing Zombies - Unref-ing pipelines waiting for async change

Mailing List SVR
Try to set the pipe to NULL and then unref should work,

Nicola

Il 10/08/2011 14:10, Wes Miller ha scritto:

> Hi All,
>
> I have a program with a receiver pipeline (essentially,
> udpsrc->decodebin->autoaudiosinkl) that may or may not do any receiving
> depending on if another program connects to it.  The pipe is set up and gets
> to the point in the code where it is "hung" in async state waiting on the
> external connection to send in some data.
>
> Later on when it's time to shut the program down, I send an EOS to the
> "hung" receiver pipe, but since the pipeline is not complete and, therefore,
> not moving data down the pipe, the EOS has no effect.
>
> So, what's the best way to handle this? I am sure there has to be a better
> way than what I've considered:
>
> 1. Use a separate variable that is true only if the pipe is in "Running"
> state and use that var to just not bother with the EOS.  If I do that, what
> do I need to do besides unref the pipeline?  Will it unref while it is in
> "async" state?  Can I move it to some other state, like "NULL" and then
> deref it?
>
> 2.  Get the state of the pipe and just deref it if the state is async?  Can
> I ask the same pipe for its state twice, i.e. will the
> gst_element_get_state() functions collide?  Interfere with each other?
> Crash?
>
> 3. Hold off on linking the pads in the New-Decoded-Pad signal callback and
> wait for a signal from udpsrc to say it has data before linking?  Would this
> make it easier to move the pipeline back to "NULL" state?
>
> 4. Use a split src consisting of the udpsrc and a audiotestsrc connected to
> a selector and send myself a burst of data to prime the pipe then change
> inputs to the udssrc?  This one is going to require an example pipe spec.
>
> 5. Is there an "interrupt state change" mechanism for the pipeline?
>
> Thanks for any help.
>
> Wes
>
>
>
>
> --
> View this message in context: http://gstreamer-devel.966125.n4.nabble.com/Killing-Zombies-Unref-ing-pipelines-waiting-for-async-change-tp3732732p3732732.html
> Sent from the GStreamer-devel mailing list archive at Nabble.com.
> _______________________________________________
> gstreamer-devel mailing list
> [hidden email]
> http://lists.freedesktop.org/mailman/listinfo/gstreamer-devel
>

_______________________________________________
gstreamer-devel mailing list
[hidden email]
http://lists.freedesktop.org/mailman/listinfo/gstreamer-devel
Reply | Threaded
Open this post in threaded view
|

Re: Killing Zombies - Unref-ing pipelines waiting for async change

Wes Miller
Administrator
Sadly, this doesn't seem to be enough.

Here is my current, not working code.  The comments tell what's happening.
I am working in eclipse using its debugger.  Many messages get clobbered.
m_whatever implies member of an object.  This code is part of my object destructor.

  
      if ( m_pipeline_recv )
      {
         if ( GST_STATE_CHANGE_ASYNC == gst_element_get_state( m_pipeline_recv, NULL, NULL, 0 ) )
         {
            gst_element_set_locked_state( m_audioDecoder, TRUE );  // m_audioDecode is Decodebin
            gst_element_abort_state( m_audioDecoder );
            gst_element_set_locked_state( m_audioDecoder, FALSE );

            m_stateChgRc_recv = gst_element_get_state( m_pipeline_recv, NULL, NULL, 1 );         // returns ASYNC
            m_stateChgRc_recv = gst_element_set_state( m_pipeline_recv, GST_STATE_NULL );  // returns SUCCESS

            gst_object_unref( GST_OBJECT ( m_pipeline_recv ));  // returns a CRITICAL message about an invalid 
                                                                                             // G_Object.    WHY?????? 
                                                                                             // The g-print that says "Asynch state changed" that
                                                                                             // follows the gst_element_get_state(...) in the main
                                                                                             // method now prints.  
            m_pipeline_recv = 0;

            gst_object_unref( GST_OBJECT ( m_loop ));
            m_loop = 0;
         }
         else
         {
            SendReceiveEOS();

            while ( m_pipeline_recv )
               msleep( 100 );
         }
      }
Reply | Threaded
Open this post in threaded view
|

Re: Killing Zombies - Unref-ing pipelines waiting for async change

michael smith-6-3
You didn't attach your code.

Anyway: the answer given was accurate. You don't need a pipeline to be
EOS to stop it. Setting the state to NULL then unreffing it is
sufficient.

If that's not working, you're running into a bug somewhere. Could be
GStreamer, more likely in your code.

Mike


On Wed, Aug 10, 2011 at 3:01 PM, Wes Miller <[hidden email]> wrote:

> Sadly, this doesn't seem to be enough.
>
> Here is my current, not working code.  The comments tell what's happening.
> I am working in eclipse using its debugger.  Many messages get clobbered.
> m_whatever implies member of an object.  This code is part of my object
> destructor.
>
>
>
> --
> View this message in context: http://gstreamer-devel.966125.n4.nabble.com/Killing-Zombies-Unref-ing-pipelines-waiting-for-async-change-tp3732732p3734436.html
> Sent from the GStreamer-devel mailing list archive at Nabble.com.
> _______________________________________________
> gstreamer-devel mailing list
> [hidden email]
> http://lists.freedesktop.org/mailman/listinfo/gstreamer-devel
>
_______________________________________________
gstreamer-devel mailing list
[hidden email]
http://lists.freedesktop.org/mailman/listinfo/gstreamer-devel
Reply | Threaded
Open this post in threaded view
|

Re: Killing Zombies - Unref-ing pipelines waiting for async change

Wes Miller
Administrator
Michael, the code is in the note itself.  I didn't paste in all the unrelated pipe building stuff and my first note said "I have a program with a receiver pipeline (essentially, udpsrc->decodebin->autoaudiosinkl".  

This has turned into an interesting problem.  Michael and Nicola were correct.  The use of:
            gst_element_set_locked_state( m_audioDecoder, TRUE );  // m_audioDecode is Decodebin
            gst_element_abort_state( m_audioDecoder );
            gst_element_set_locked_state( m_audioDecoder, FALSE );
created problems and isn't needed.

The part I left out of my explanation, apologies to all, the pipeline was running in a separate thread from the class destructor that was trying to kill off the "stuck", async, pipeline.   It was coded more or less as in all the examples:
      g_signal_connect( m_recvDecoder, "new-decoded-pad", G_CALLBACK( on_recv_pad_decoded ), (gpointer)m_recvIdentity );


      /*--- Set the pipelines to "playing" state---*/
      g_print( "\nReceive pipeline - change pipeline state to GST_STATE_PLAYING. \n\n" );
      m_stateChgRc_recv = gst_element_set_state( m_recvPipeline, GST_STATE_PLAYING );
      g_print( "\nReceive pipeline - state change rc = %d \n\n", m_stateChgRc_recv );

      gst_element_get_state( m_recvPipeline, NULL, NULL, -1 ) ;
      g_print( "Recv pipeline - Async state change completed.  rc = %d \n", m_stateChgRc_recv );

      /*--- Let the pipelines iterate until an EOS is received ---*/
      g_print( "\nReceive pipelines - Running...\n\n" );
      g_main_loop_run( m_loop );

      /*--- Beyond the main loop, clean up nicely ---*/
      g_print( "Receive pipeline - Returned, stopping playback\n" );
      gst_element_set_state( m_recvPipeline, GST_STATE_NULL );

      g_print( "Receive pipeline - Deleting receive pipeline\n" );
      g_main_loop_quit( m_loop );

      gst_object_unref( GST_OBJECT ( m_recvPipeline ));
      m_recvPipeline = 0;

      gst_object_unref( GST_OBJECT ( m_loop ));
      m_loop = 0;

Here is what was happening:
The destructor, in its separate thread, set the recvPipeline state to NULL and unrefed the pipeline and loop.  
In the pipeline's thread, the gst_element_get_state() was no longer ASYNC so the gst_element_get_state() returned and the code above resumed trying to run the (unref-ed)pipeline and enter the (unref-ed)main loop.  This spit out all sorts of CRITICAL messages and warnings about invalid objects and refcounts > 0.

The fix was to,
1. remove the unrefs from the destructor, letting the other thread handle those operations.  Then  
2.fix the pipeline code thus:

      GstState now, pending;

      gst_element_get_state( m_recvPipeline, &now, &pending, -1 ) ;
      g_print( "Recv pipeline - Async state change completed.  rc = %d \n", m_stateChgRc_recv );
      g_print( "Recv pipeline - now = %d \n                pendiong = %d\n", (int)now, (int)pending );

      /*--- Let the pipelines iterate until an EOS is received or state != PLAYING---*/
      if ( GST_STATE_PLAYING == now )
      {
         g_print( "\nReceive pipelines - Running...\n\n" );
         g_main_loop_run( m_loop );
      }

      /*--- Beyond the main loop, clean up nicely ---*/
      g_print( "Receive pipeline - Returned, stopping playback\n" );
      gst_element_set_state( m_recvPipeline, GST_STATE_NULL );

      g_print( "Receive pipeline - Deleting receive pipeline\n" );
      g_main_loop_quit( m_loop );
      gst_object_unref( GST_OBJECT ( m_recvPipeline ));
      m_recvPipeline = 0;

      gst_object_unref( GST_OBJECT ( m_loop ));
      m_loop = 0;

Hope this helps the next guy and many thanks to Nicola and Michael.

Wes
Reply | Threaded
Open this post in threaded view
|

Re: Killing Zombies - Unref-ing pipelines waiting for async change

Edward Hervey
Administrator
On Thu, 2011-08-11 at 05:45 -0700, Wes Miller wrote:
> Michael, the code is in the note itself.

 ... No, it's not. It *might* be in nabble (haven't looked), but doesn't
get properly transferred to the gazillion other people using the
standard way of using mailing-lists.

   Please use the proper tools... or get nabble to fix their code.

    Edward

_______________________________________________
gstreamer-devel mailing list
[hidden email]
http://lists.freedesktop.org/mailman/listinfo/gstreamer-devel
Reply | Threaded
Open this post in threaded view
|

Re: Killing Zombies - Unref-ing pipelines waiting for async change

Wes Miller
Administrator
Harvey,

Of course, you are right.  Nabble has the code I included in the note but when I looked at http://lists.freedesktop.org/archives/gstreamer-devel/2011-August/032635.html, it isn't there.  That's sad.  I've never seen Nabble misfire before and I hate having a mailbox full of list postings and I'm just not fond of digest-form forum reading either.  Is there another tool you can suggest?  A quick Google query on mailing list readers is not promising.

Anyway, My apologies to all.  I thought it was there.  I just thought you were zsaying I'd forgotten to attach a file.  Mea culpa.

Wes
Reply | Threaded
Open this post in threaded view
|

Re: Killing Zombies - Unref-ing pipelines waiting for async change

Wes Miller
Administrator
This post was updated on .
In reply to this post by Wes Miller
I missed an error in my code for the pipeline thread.  I wrote:

gst_object_unref( GST_OBJECT ( m_loop ));
m_loop = 0;

You can't unref a GMainLoop using gst_object_unref!.  A loop is not a GST_OBJECT.  The call producea  G_Object warnings and errors that took me forever to find.  Instead, of course, use g_main_loop_unref().

I note that some gstreamer examples I've seen, including a couple in the docs, omit this step.  I wanted to make sure that my pipeline thread(s) freed any refs and memory for the loop.

Wes
Reply | Threaded
Open this post in threaded view
|

Re: Killing Zombies - Unref-ing pipelines waiting for async change

Wes Miller
Administrator
In reply to this post by Wes Miller
I also see at http://lists.freedesktop.org/archives/gstreamer-devel/2011-August/032658.html that my code in this note got deleted.  My apologies to anyone reading this thread in the forum.

FWIW, the RAW tag in naabble seems to be the OMIT-THIS tag.
Re-posting for posterity:

----------------------------------------------------------------------------------------------

This has turned into an interesting problem.  Michael and Nicola were correct.  The use of:

            gst_element_set_locked_state( m_audioDecoder, TRUE );  // m_audioDecode is Decodebin
            gst_element_abort_state( m_audioDecoder );
            gst_element_set_locked_state( m_audioDecoder, FALSE );

created problems and isn't needed.

The part I left out of my explanation, apologies to all, the pipeline was running in a separate thread from the class destructor that was trying to kill off the "stuck", async, pipeline.   It was coded more or less as in all the examples:

      g_signal_connect( m_recvDecoder, "new-decoded-pad", G_CALLBACK( on_recv_pad_decoded ), (gpointer)m_recvIdentity );


      /*--- Set the pipelines to "playing" state---*/
      g_print( "\nReceive pipeline - change pipeline state to GST_STATE_PLAYING. \n\n" );
      m_stateChgRc_recv = gst_element_set_state( m_recvPipeline, GST_STATE_PLAYING );
      g_print( "\nReceive pipeline - state change rc = %d \n\n", m_stateChgRc_recv );

      gst_element_get_state( m_recvPipeline, NULL, NULL, -1 ) ;
      g_print( "Recv pipeline - Async state change completed.  rc = %d \n", m_stateChgRc_recv );

      /*--- Let the pipelines iterate until an EOS is received ---*/
      g_print( "\nReceive pipelines - Running...\n\n" );
      g_main_loop_run( m_loop );

      /*--- Beyond the main loop, clean up nicely ---*/
      g_print( "Receive pipeline - Returned, stopping playback\n" );
      gst_element_set_state( m_recvPipeline, GST_STATE_NULL );

      g_print( "Receive pipeline - Deleting receive pipeline\n" );
      g_main_loop_quit( m_loop );

      gst_object_unref( GST_OBJECT ( m_recvPipeline ));
      m_recvPipeline = 0;

      gst_object_unref( GST_OBJECT ( m_loop ));
      m_loop = 0;


Here is what was happening:
The destructor, in its separate thread, set the recvPipeline state to NULL and unrefed the pipeline and loop.  
In the pipeline's thread, the gst_element_get_state() was no longer ASYNC so the gst_element_get_state() returned and the code above resumed trying to run the (unref-ed)pipeline and enter the (unref-ed)main loop.  This spit out all sorts of CRITICAL messages and warnings about invalid objects and refcounts > 0.

The fix was to,
1. remove the unrefs from the destructor, letting the other thread handle those operations.  Then  
2.fix the pipeline code thus:


      GstState now, pending;

      gst_element_get_state( m_recvPipeline, &now, &pending, -1 ) ;
      g_print( "Recv pipeline - Async state change completed.  rc = %d \n", m_stateChgRc_recv );
      g_print( "Recv pipeline - now = %d \n                pendiong = %d\n", (int)now, (int)pending );

      /*--- Let the pipelines iterate until an EOS is received or state != PLAYING---*/
      if ( GST_STATE_PLAYING == now )
      {
         g_print( "\nReceive pipelines - Running...\n\n" );
         g_main_loop_run( m_loop );
      }

      /*--- Beyond the main loop, clean up nicely ---*/
      g_print( "Receive pipeline - Returned, stopping playback\n" );
      gst_element_set_state( m_recvPipeline, GST_STATE_NULL );

      g_print( "Receive pipeline - Deleting receive pipeline\n" );
      g_main_loop_quit( m_loop );
      gst_object_unref( GST_OBJECT ( m_recvPipeline ));
      m_recvPipeline = 0;

      gst_object_unref( GST_OBJECT ( m_loop ));
      m_loop = 0;


Hope this helps the next guy and many thanks to Nicola and Michael.

Wes
Reply | Threaded
Open this post in threaded view
|

Re: Killing Zombies - Unref-ing pipelines waiting for async change

Edward Hervey
Administrator
In reply to this post by Wes Miller
On Fri, 2011-08-12 at 10:42 -0700, Wes Miller wrote:
> Harvey,
>
> Of course, you are right.  Nabble has the code I included in the note but
> when I looked at
> http://lists.freedesktop.org/archives/gstreamer-devel/2011-August/032635.html,
> it isn't there.  That's sad.  I've never seen Nabble misfire before and I
> hate having a mailbox full of list postings and I'm just not fond of
> digest-form forum reading either.  Is there another tool you can suggest?  A
> quick Google query on mailing list readers is not promising.

  Any decent mail client (or online services like gmail) will allow you
to "Filter by Mailing List", which you can then put into a folder.
  It won't spam your inbox, and you'll know exactly what you've read or
not.

>
> Anyway, My apologies to all.  I thought it was there.  I just thought you
> were zsaying I'd forgotten to attach a file.  Mea culpa.

  Not a big problem, just creates inconsistencies :)

    Edward

>
> Wes
>
> --
> View this message in context: http://gstreamer-devel.966125.n4.nabble.com/Killing-Zombies-Unref-ing-pipelines-waiting-for-async-change-tp3732732p3740003.html
> Sent from the GStreamer-devel mailing list archive at Nabble.com.
> _______________________________________________
> gstreamer-devel mailing list
> [hidden email]
> http://lists.freedesktop.org/mailman/listinfo/gstreamer-devel


_______________________________________________
gstreamer-devel mailing list
[hidden email]
http://lists.freedesktop.org/mailman/listinfo/gstreamer-devel
Reply | Threaded
Open this post in threaded view
|

Re: Killing Zombies - Unref-ing pipelines waiting for async change

Stefan Sauer
In reply to this post by Wes Miller
Hi Wes,
On 08/12/11 19:47, Wes Miller wrote:

> I missed an error in my code for the pipeline thread.  I wrote:
>
> gst_object_unref( GST_OBJECT ( m_loop ));
> m_loop = 0;
>
> You can't unref a GMainLoop!  Produced a G_Object warning and error that
> took me forever to find.  Instead, of course, use g_main_loop_unref().
>
> I note that some gstreamer examples I've seen, including a couple in the
> docs, omit this step.  I wanted to make sure that my pipeline thread(s)
> freed any refs and memory for the loop.
Going systematically over the examples (by means of grep or the like)
and providing patches to clean things up is a great way to contribute.

Stefan

> Wes
>
> --
> View this message in context: http://gstreamer-devel.966125.n4.nabble.com/Killing-Zombies-Unref-ing-pipelines-waiting-for-async-change-tp3732732p3740019.html
> Sent from the GStreamer-devel mailing list archive at Nabble.com.
> _______________________________________________
> gstreamer-devel mailing list
> [hidden email]
> http://lists.freedesktop.org/mailman/listinfo/gstreamer-devel

_______________________________________________
gstreamer-devel mailing list
[hidden email]
http://lists.freedesktop.org/mailman/listinfo/gstreamer-devel