<div>Hi Gruner£º</div><div><br></div><div>The source code is pasted below, and in the attachment. We use gst_alloc to create a gstreamer, and call gst_destructor to stop gstreamer from playing, bofore EOF was reached.</div><div><br></div><div>Please tell us if we had a bad use, or something bad was triggered.</div><div><br></div><div>Thanks.</div><div><br></div><div><div><br></div><div>struct ausrc_st {</div><div><span style="white-space:pre">       </span>const struct ausrc *as;     /**< Inheritance             */</div><div><br></div><div><span style="white-space:pre">     </span>pthread_t tid;              /**< Thread ID               */</div><div><span style="white-space:pre">     </span>bool run;                   /**< Running flag            */</div><div>   </div><div>    ...</div><div><br></div><div><span style="white-space:pre">   </span>/* Gstreamer */</div><div><span style="white-space:pre">       </span>char *uri;</div><div><span style="white-space:pre">    </span>GstElement *pipeline, *bin, *source, *capsfilt, *sink;</div><div><span style="white-space:pre">        </span>GMainLoop *loop;</div><div>};</div><div><br></div><div>static void *thread(void *arg)</div><div>{</div><div><span style="white-space:pre">       </span>struct ausrc_st *st = arg;</div><div><span style="white-space:pre">    </span>gst_element_set_state(st->pipeline, GST_STATE_PLAYING);</div><div><br></div><div><span style="white-space:pre">   </span>while (st->run) {</div><div><span style="white-space:pre">          </span>g_main_loop_run(st->loop);</div><div><span style="white-space:pre"> </span>}</div><div><br></div><div><span style="white-space:pre">    </span>//deadlock will happen in this line</div><div><span style="white-space:pre">   </span>gst_element_set_state(st->pipeline, GST_STATE_NULL);</div><div><span style="white-space:pre">       </span>return NULL;</div><div>}</div><div><br></div><div><br></div><div>static gboolean bus_watch_handler(GstBus *bus, GstMessage *msg, gpointer data)</div><div>{</div><div><span style="white-space:pre">   </span>struct ausrc_st *st = data;</div><div><span style="white-space:pre">   </span>GMainLoop *loop = st->loop;</div><div><span style="white-space:pre">        </span>(void)bus;</div><div><span style="white-space:pre">    </span>switch (GST_MESSAGE_TYPE(msg)) {</div><div><br></div><div><span style="white-space:pre">     </span>case GST_MESSAGE_EOS:</div><div><br></div><div><span style="white-space:pre">                </span>break;</div><div><br></div><div><span style="white-space:pre">       </span>case GST_MESSAGE_ERROR:</div><div><span style="white-space:pre">               </span>st->run = false;</div><div><span style="white-space:pre">           </span>g_main_loop_quit(loop);</div><div><span style="white-space:pre">               </span>break;</div><div><span style="white-space:pre">        </span>default:</div><div><span style="white-space:pre">              </span>break;</div><div><span style="white-space:pre">        </span>}</div><div><br></div><div><span style="white-space:pre">    </span>return TRUE;</div><div>}</div><div><br></div><div><br></div><div>static void handoff_handler(GstFakeSink *fakesink, GstBuffer *buffer,</div><div>                            GstPad *pad, gpointer user_data)</div><div>{</div><div><span style="white-space:pre">   </span>struct ausrc_st *st = user_data;</div><div><br></div><div><span style="white-space:pre">     </span>(void)fakesink;</div><div><span style="white-space:pre">       </span>(void)pad;</div><div><br></div><div><span style="white-space:pre">   </span>// ... get data from buffer and sleep.</div><div>}</div><div><br></div><div>/**</div><div> * Set up the Gstreamer pipeline. The playbin element is used to decode</div><div> * all kinds of different formats. The capsfilter is used to deliver the</div><div> * audio in a fixed format (X Hz, 1-2 channels, 16 bit signed)</div><div> *</div><div> * The pipeline looks like this:</div><div> *</div><div> * <pre></div><div> *  .--------------.    .------------------------------------------.</div><div> *  |    playbin   |    |mybin    .------------.   .------------.  |</div><div> *  |----.    .----|    |-----.   | capsfilter |   |  fakesink  |  |</div><div> *  |sink|    |src |--->|ghost|   |----.   .---|   |----.   .---|  |    handoff</div><div> *  |----'    '----|    |pad  |-->|sink|   |src|-->|sink|   |src|--+--> handler</div><div> *  |              |    |-----'   '------------'   '------------'  |</div><div> *  '--------------'    '------------------------------------------'</div><div> * </pre></div><div> *</div><div> * @param st Audio source state</div><div> *</div><div> * @return 0 if success, otherwise errorcode</div><div> */</div><div><br></div><div>static int gst_setup(struct ausrc_st *st)</div><div>{</div><div><span style="white-space:pre">     </span>GstBus *bus;</div><div><span style="white-space:pre">  </span>GstPad *pad;</div><div><br></div><div><span style="white-space:pre"> </span>st->loop = g_main_loop_new(NULL, FALSE);</div><div><br></div><div><span style="white-space:pre">  </span>st->pipeline = gst_pipeline_new("pipeline");</div><div><span style="white-space:pre">     </span>if (!st->pipeline) {</div><div><span style="white-space:pre">               </span>warning("gst: failed to create pipeline element\n");</div><div><span style="white-space:pre">                </span>return ENOMEM;</div><div><span style="white-space:pre">        </span>}</div><div><br></div><div><span style="white-space:pre">    </span>/********************* Player BIN **************************/</div><div><br></div><div><span style="white-space:pre">        </span>st->source = gst_element_factory_make("playbin", "source");</div><div><span style="white-space:pre">    </span>if (!st->source) {</div><div><span style="white-space:pre">         </span>warning("gst: failed to create playbin source element\n");</div><div><span style="white-space:pre">          </span>return ENOMEM;</div><div><span style="white-space:pre">        </span>}</div><div><br></div><div><span style="white-space:pre">    </span>/********************* My BIN **************************/</div><div><br></div><div><span style="white-space:pre">    </span>st->bin = gst_bin_new("mybin");</div><div><br></div><div><span style="white-space:pre"> </span>st->capsfilt = gst_element_factory_make("capsfilter", NULL);</div><div><span style="white-space:pre">     </span>if (!st->capsfilt) {</div><div><span style="white-space:pre">               </span>warning("gst: failed to create capsfilter element\n");</div><div><span style="white-space:pre">              </span>return ENOMEM;</div><div><span style="white-space:pre">        </span>}</div><div><br></div><div><span style="white-space:pre">    </span>set_caps(st);</div><div><br></div><div><span style="white-space:pre">        </span>st->sink = gst_element_factory_make("fakesink", "sink");</div><div><span style="white-space:pre">       </span>if (!st->sink) {</div><div><span style="white-space:pre">           </span>warning("gst: failed to create sink element\n");</div><div><span style="white-space:pre">            </span>return ENOMEM;</div><div><span style="white-space:pre">        </span>}</div><div><br></div><div><span style="white-space:pre">    </span>gst_bin_add_many(GST_BIN(st->bin), st->capsfilt, st->sink, NULL);</div><div><span style="white-space:pre">    </span>gst_element_link_many(st->capsfilt, st->sink, NULL);</div><div><br></div><div><span style="white-space:pre">   </span>/* add ghostpad */</div><div><span style="white-space:pre">    </span>pad = gst_element_get_pad(st->capsfilt, "sink");</div><div><span style="white-space:pre"> </span>gst_element_add_pad(st->bin, gst_ghost_pad_new("sink", pad));</div><div><span style="white-space:pre">    </span>gst_object_unref(GST_OBJECT(pad));</div><div><br></div><div><span style="white-space:pre">   </span>/* put all elements in a bin */</div><div><span style="white-space:pre">       </span>gst_bin_add_many(GST_BIN(st->pipeline), st->source, NULL);</div><div><br></div><div><span style="white-space:pre">     </span>/* Override audio-sink handoff handler */</div><div><span style="white-space:pre">     </span>g_object_set(G_OBJECT(st->sink), "signal-handoffs", TRUE, NULL);</div><div><span style="white-space:pre"> </span>g_signal_connect(st->sink, "handoff", G_CALLBACK(handoff_handler), st);</div><div><span style="white-space:pre">  </span>g_object_set(G_OBJECT(st->source), "audio-sink", st->bin, NULL);</div><div><br></div><div><span style="white-space:pre">     </span>/********************* Misc **************************/</div><div><br></div><div><span style="white-space:pre">      </span>/* Bus watch */</div><div><span style="white-space:pre">       </span>bus = gst_pipeline_get_bus(GST_PIPELINE(st->pipeline));</div><div><span style="white-space:pre">    </span>gst_bus_add_watch(bus, bus_watch_handler, st);</div><div><span style="white-space:pre">        </span>gst_object_unref(bus);</div><div><br></div><div><span style="white-space:pre">       </span>/* Set URI */</div><div><span style="white-space:pre"> </span>g_object_set(G_OBJECT(st->source), "uri", st->uri, NULL);</div><div><br></div><div><span style="white-space:pre">    </span>return 0;</div><div>}</div><div><br></div><div><br></div><div><br></div><div>static void gst_destructor(void *arg)</div><div>{</div><div><span style="white-space:pre">      </span>struct ausrc_st *st = arg;</div><div><span style="white-space:pre">    </span>int err = 0;</div><div><span style="white-space:pre">  </span>if (st->run) {</div><div><span style="white-space:pre">             </span>st->run = false;</div><div><span style="white-space:pre">           </span>g_main_loop_quit(st->loop);</div><div><span style="white-space:pre">                </span>err = pthread_join(st->tid, NULL);</div><div><span style="white-space:pre"> </span>}</div><div><span style="white-space:pre">     </span>//deadlock will happen in this line</div><div><span style="white-space:pre">   </span>gst_element_set_state(st->pipeline, GST_STATE_NULL);</div><div><span style="white-space:pre">       </span>gst_object_unref(GST_OBJECT(st->pipeline));</div><div><span style="white-space:pre">        </span>mem_deref(st->call_id);</div><div><span style="white-space:pre">    </span>mem_deref(st->uri);</div><div><span style="white-space:pre">        </span>mem_deref(st->aubuf);</div><div>}</div><div><br></div><div><br></div><div>static int gst_alloc(struct ausrc_st **stp, const struct ausrc *as,</div><div>                     struct media_ctx **ctx,</div><div>                     struct ausrc_prm *prm, const char *device, const char *call_id,</div><div>                     ausrc_read_h *rh, ausrc_error_h *errh, void *arg)</div><div>{</div><div><span style="white-space:pre">  </span>struct ausrc_st *st;</div><div><span style="white-space:pre">  </span>int err;</div><div><span style="white-space:pre">      </span>(void)ctx;</div><div><span style="white-space:pre">    </span>err = gst_setup(st);</div><div><span style="white-space:pre">  </span>if (err)</div><div><span style="white-space:pre">              </span>goto out;</div><div><br></div><div><span style="white-space:pre">    </span>st->run  = true;</div><div><span style="white-space:pre">      </span>err = pthread_create(&st->tid, NULL, thread, st);</div><div><span style="white-space:pre">      </span>if (err) {</div><div><span style="white-space:pre">            </span>st->run = false;</div><div><span style="white-space:pre">           </span>goto out;</div><div><span style="white-space:pre">     </span>}</div><div><br></div><div>out:</div><div><span style="white-space:pre"> </span>if (err)</div><div><span style="white-space:pre">              </span>mem_deref(st);</div><div><span style="white-space:pre">        </span>else</div><div><span style="white-space:pre">          </span>*stp = st;</div><div><br></div><div><span style="white-space:pre">   </span>return err;</div><div>}</div></div><div><div><br></div><div><br></div><div style="font-size: 12px;font-family: Arial Narrow;padding:2px 0 2px 0;">------------------ Original ------------------</div><div style="font-size: 12px;background:#efefef;padding:8px;"><div><b>From: </b> "Michael Gruner"<michael.gruner@ridgerun.com>;</div><div><b>Date: </b> Tue, Jan 15, 2019 07:20 AM</div><div><b>To: </b> "Êæ¿Æ"<shuke987@qq.com>;"Discussion of the development of and with GStreamer"<gstreamer-devel@lists.freedesktop.org>;<wbr></div><div></div><div><b>Subject: </b> Re: deadlock when stop gstreamer</div></div><div><br></div>Hi<br><br>Can you share the source code? Or at least a minimal example that is able to reproduce this issue?<br><br>Michael<br><br>> On Jan 12, 2019, at 7:36 AM, Shuke <shuke987@qq.com> wrote:<br>> <br>> Guys,<br>> I had a trouble when try to stop gstreamer . I want to stop playing before<br>> EOF, using gst_element_set_state function. But the call never return, and<br>> deadlock happened. <br>> <br>> Pipeline looks like:<br>> .--------------.       .------------------------------------------.<br>> |    playbin   |       |mybin    .------------.     .------------.  |<br>> |----.     .----|       |-----.     | capsfilter |     |  fakesink  |  |<br>> |sink|    |src |---> |ghost|   |----.   .---|      |----.   .---|  |   <br>> handoff<br>> |----'     '----|       |pad  |-->|sink|   |src|-->|sink|   |src|--+--><br>> handler<br>> |                 |       |-----'      '------------'     '------------'  |<br>> '--------------'       '------------------------------------------'<br>> <br>> and bt is:<br>> (gdb) thread apply all bt<br>> <br>> Thread 4 (Thread 0x7fb57b1aa700 (LWP 28534)):<br>> #0  0x00007fb58cc0a66d in nanosleep () at /lib64/libc.so.6<br>> #1  0x00007fb58cc3b2f4 in usleep () at /lib64/libc.so.6<br>> #2  0x00007fb58d03b66d in Report::DoReport(void*) ()<br>>    at /usr/local/cvd/sip-user-agent/sip-plugin/build/libsip-plugin.so<br>> #3  0x00007fb586f56070 in  () at /lib64/libstdc++.so.6<br>> #4  0x00007fb58d8a3dc5 in start_thread () at /lib64/libpthread.so.0<br>> #5  0x00007fb58cc4376d in clone () at /lib64/libc.so.6<br>> <br>> Thread 3 (Thread 0x7fb568a6b700 (LWP 2929)):<br>> #0  0x00007fb58d8aa1bd in __lll_lock_wait () at /lib64/libpthread.so.0<br>> #1  0x00007fb58d8a5d1d in _L_lock_840 () at /lib64/libpthread.so.0<br>> #2  0x00007fb58d8a5c3a in pthread_mutex_lock () at /lib64/libpthread.so.0<br>> #3  0x00007fb582b1da31 in g_static_rec_mutex_lock () at<br>> /lib64/libglib-2.0.so.0<br>> #4  0x00007fb56bbb90a2 in new_pad () at<br>> /usr/lib64/gstreamer-0.10/libgstdecodebin.so<br>> #5  0x00007fb56bbb91ac in new_caps () at<br>> /usr/lib64/gstreamer-0.10/libgstdecodebin.so<br>> #6  0x00007fb583593ac8 in g_closure_invoke () at /lib64/libgobject-2.0.so.0<br>> #7  0x00007fb5835a616d in signal_emit_unlocked_R () at<br>> /lib64/libgobject-2.0.so.0<br>> #8  0x00007fb5835ae1e1 in g_signal_emit_valist () at<br>> /lib64/libgobject-2.0.so.0<br>> #9  0x00007fb5835ae4cf in g_signal_emit () at /lib64/libgobject-2.0.so.0<br>> #10 0x00007fb5835983a4 in g_object_dispatch_properties_changed () at<br>> /lib64/libgobject-2.0.so.0<br>> #11 0x00007fb5837fcf74 in gst_object_dispatch_properties_changed () at<br>> /lib64/libgstreamer-0.10.so.0<br>> #12 0x00007fb58359a8d9 in g_object_notify_by_pspec () at<br>> /lib64/libgobject-2.0.so.0<br>> #13 0x00007fb58382b8d4 in gst_pad_set_caps () at<br>> /lib64/libgstreamer-0.10.so.0<br>> #14 0x00007fb56af7b4d4 in gst_mpeg_audio_parse_parse_frame () at<br>> /usr/lib64/gstreamer-0.10/libgstaudioparsers.so<br>> #15 0x00007fb5782b9124 in gst_base_parse_handle_and_push_frame.isra.7 () at<br>> /usr/lib64/libgstbase-0.10.so.0<br>> #16 0x00007fb5782bbc43 in gst_base_parse_loop () at<br>> /usr/lib64/libgstbase-0.10.so.0<br>> #17 0x00007fb583856a14 in gst_task_func () at /lib64/libgstreamer-0.10.so.0<br>> #18 0x00007fb582b7230c in g_thread_pool_thread_proxy () at<br>> /lib64/libglib-2.0.so.0<br>> #19 0x00007fb582b71970 in g_thread_proxy () at /lib64/libglib-2.0.so.0<br>> #20 0x00007fb58d8a3dc5 in start_thread () at /lib64/libpthread.so.0<br>> #21 0x00007fb58cc4376d in clone () at /lib64/libc.so.6<br>> <br>> Thread 2 (Thread 0x7fb57958e700 (LWP 3324)):<br>> #0  0x00007fb58d8aa1bd in __lll_lock_wait () at /lib64/libpthread.so.0<br>> #1  0x00007fb58d8a5d1d in _L_lock_840 () at /lib64/libpthread.so.0<br>> #2  0x00007fb58d8a5c3a in pthread_mutex_lock () at /lib64/libpthread.so.0<br>> #3  0x00007fb582b1da31 in g_static_rec_mutex_lock () at<br>> /lib64/libglib-2.0.so.0<br>> #4  0x00007fb5782b4825 in gst_base_parse_activate () at<br>> /usr/lib64/libgstbase-0.10.so.0<br>> #5  0x00007fb5782b48df in gst_base_parse_sink_activate_pull () at<br>> /usr/lib64/libgstbase-0.10.so.0<br>> #6  0x00007fb58382f401 in gst_pad_activate_pull () at<br>> /lib64/libgstreamer-0.10.so.0<br>> #7  0x00007fb58382ff37 in gst_pad_set_active () at<br>> /lib64/libgstreamer-0.10.so.0<br>> #8  0x00007fb583811f21 in activate_pads () at /lib64/libgstreamer-0.10.so.0<br>> #9  0x00007fb58382325d in gst_iterator_fold () at<br>> /lib64/libgstreamer-0.10.so.0<br>> #10 0x00007fb583811fab in iterator_activate_fold_with_resync () at<br>> /lib64/libgstreamer-0.10.so.0<br>> #11 0x00007fb58381459d in gst_element_pads_activate () at<br>> /lib64/libgstreamer-0.10.so.0<br>> #12 0x00007fb583814874 in gst_element_change_state_func () at<br>> /lib64/libgstreamer-0.10.so.0<br>> #13 0x00007fb5782b571d in gst_base_parse_change_state () at<br>> /usr/lib64/libgstbase-0.10.so.0<br>> #14 0x00007fb5838163b2 in gst_element_change_state () at<br>> /lib64/libgstreamer-0.10.so.0<br>> #15 0x00007fb583816a23 in gst_element_set_state_func () at<br>> /lib64/libgstreamer-0.10.so.0<br>> #16 0x00007fb583804412 in gst_bin_change_state_func () at<br>> /lib64/libgstreamer-0.10.so.0<br>> #17 0x00007fb56bbb7441 in gst_decode_bin_change_state () at<br>> /usr/lib64/gstreamer-0.10/libgstdecodebin.so<br>> #18 0x00007fb5838163b2 in gst_element_change_state () at<br>> /lib64/libgstreamer-0.10.so.0<br>> #19 0x00007fb583816a23 in gst_element_set_state_func () at<br>> /lib64/libgstreamer-0.10.so.0<br>> #20 0x00007fb583804412 in gst_bin_change_state_func () at<br>> /lib64/libgstreamer-0.10.so.0<br>> #21 0x00007fb583834552 in gst_pipeline_change_state () at<br>> /lib64/libgstreamer-0.10.so.0<br>> #22 0x00007fb578b6e8fd in gst_play_base_bin_change_state () at<br>> /usr/lib64/gstreamer-0.10/libgstplaybin.so<br>> #23 0x00007fb578b55665 in gst_play_bin_change_state () at<br>> /usr/lib64/gstreamer-0.10/libgstplaybin.so<br>> #24 0x00007fb5838163b2 in gst_element_change_state () at<br>> /lib64/libgstreamer-0.10.so.0<br>> #25 0x00007fb583816a23 in gst_element_set_state_func () at<br>> /lib64/libgstreamer-0.10.so.0<br>> #26 0x00007fb583804412 in gst_bin_change_state_func () at<br>> /lib64/libgstreamer-0.10.so.0<br>> #27 0x00007fb583834552 in gst_pipeline_change_state () at<br>> /lib64/libgstreamer-0.10.so.0<br>> #28 0x00007fb5838163b2 in gst_element_change_state () at<br>> /lib64/libgstreamer-0.10.so.0<br>> #29 0x00007fb583816a23 in gst_element_set_state_func () at<br>> /lib64/libgstreamer-0.10.so.0<br>> #30 0x00007fb583abfd6e in thread (arg=0x1765e7e0) at modules/gst/gst.c:93<br>> #31 0x00007fb58d8a3dc5 in start_thread () at /lib64/libpthread.so.0<br>> #32 0x00007fb58cc4376d in clone () at /lib64/libc.so.6<br>> <br>> Thread 1 (Thread 0x7fb58ea12980 (LWP 28516)):<br>> #0  0x00007fb58d8a4ef7 in pthread_join () at /lib64/libpthread.so.0<br>> #1  0x00007fb583abfdc7 in gst_destructor (arg=0x1765e7e0) at<br>> modules/gst/gst.c:423<br>> #2  0x00007fb58e5f54ba in mem_deref (data=0x1765e7e0) at src/mem/mem.c:318<br>> #3  0x000000000040ee95 in audio_set_source (au=au@entry=0x17508140,<br>> mod=mod@entry=0x7ffe4ab103d0 "gst", device=device@entry=0x7ffe4ab103e0<br>> "file:///usr/local/cvd/sip-user-agent/baresip/baresip-0.5.9/empty.mp3")<br>>    at src/audio.c:2083<br>> #4  0x00007fb57b1acc30 in switch_audio_device<br>> (session_id=session_id@entry=0x1057f108 "2d3da0e4ddd9fd1f",<br>> device=device@entry=0x0) at modules/robot/robot.c:162<br>> #5  0x00007fb57b1ace0b in switch_audio_device (session_id=0x1057f108<br>> "2d3da0e4ddd9fd1f", device=0x0)<br>>    at modules/robot/robot.c:182<br>> #6  0x00007fb58d0417ac in PlayCmd::Action() () at<br>> /usr/local/cvd/sip-user-agent/sip-plugin/build/libsip-plugin.so<br>> #7  0x00007fb58d040367 in TimerProcess() () at<br>> /usr/local/cvd/sip-user-agent/sip-plugin/build/libsip-plugin.so<br>> #8  0x00007fb57b1ac7a9 in plugin_timer_handler (arg=arg@entry=0x0) at<br>> modules/robot/robot.c:238<br>> #9  0x00007fb58e5f389c in tmr_poll (tmrl=tmrl@entry=0x7fb58e815880<br>> <global_re+32>) at src/tmr/tmr.c:113<br>> #10 0x00007fb58e5f4ce8 in re_main (signalh=signalh@entry=0x421c30<br>> <signal_handler>) at src/main/main.c:994<br>> #11 0x000000000040a356 in main (argc=<optimized out>, argv=<optimized out>)<br>> at src/main.c:242<br>> <br>> Thanks a lot.<br>> <br>> <br>> <br>> --<br>> Sent from: http://gstreamer-devel.966125.n4.nabble.com/<br>> _______________________________________________<br>> gstreamer-devel mailing list<br>> gstreamer-devel@lists.freedesktop.org<br>> https://lists.freedesktop.org/mailman/listinfo/gstreamer-devel<br><br></div>