summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJuergen Keil <jkeil@users.sourceforge.net>2002-12-20 18:14:34 +0000
committerJuergen Keil <jkeil@users.sourceforge.net>2002-12-20 18:14:34 +0000
commitb8019d2a215ba08c34997ab9314b658245ef363f (patch)
treef4163258406e628d8ee98c17b9de34ea9cedb1b2
parente315d1402cf9988403047f091964e940e1ee8b68 (diff)
downloadxine-lib-b8019d2a215ba08c34997ab9314b658245ef363f.tar.gz
xine-lib-b8019d2a215ba08c34997ab9314b658245ef363f.tar.bz2
Install a hack to avoid deadlocks when exiting xine (for exampple with the
'q' key). When detecting a 'stall' condition in video_out, the 'flush()' on the video decoder deadlocks with with the video_out close from the video_decoder thread when video_decoder sees a BUF_CONTROL_QUIT message. The two threads grab the streams_lock and the video_decoder.lock in reverse order, leading to deadlock (deadlock happens quite often on solaris). CVS patchset: 3596 CVS date: 2002/12/20 18:14:34
-rw-r--r--src/xine-engine/video_out.c48
1 files changed, 47 insertions, 1 deletions
diff --git a/src/xine-engine/video_out.c b/src/xine-engine/video_out.c
index e111ab8bb..3bffbee41 100644
--- a/src/xine-engine/video_out.c
+++ b/src/xine-engine/video_out.c
@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*
- * $Id: video_out.c,v 1.118 2002/12/16 18:57:49 miguelfreitas Exp $
+ * $Id: video_out.c,v 1.119 2002/12/20 18:14:34 jkeil Exp $
*
* frame allocation / queuing / scheduling / output functions
*/
@@ -784,6 +784,19 @@ static void *video_out_loop (void *this_gen) {
if (diff > 30000 && !this->display_img_buf_queue->first) {
xine_stream_t *stream;
+#if XINE_DEADLOCK_ON_QUIT
+ /*
+ * this flush code often deadlocks when a BUF_CONTROL_QUIT is
+ * sent to the video_decoder thread (that is, on xine exit):
+ *
+ * - we're detecting a "stall" here, this code locks
+ * streams_lock, and then video decoder's lock in the
+ * ...->flush() call
+ *
+ * - video_decoder performs actions for BUF_CONTROL_QUIT: it
+ * locks and disposes the video_decoder, which calls vo_close()
+ * and vo_close() tries to lock the streams_lock.
+ */
pthread_mutex_lock(&this->streams_lock);
for (stream = xine_list_first_content(this->streams); stream;
stream = xine_list_next_content(this->streams)) {
@@ -799,6 +812,39 @@ static void *video_out_loop (void *this_gen) {
}
}
pthread_mutex_unlock(&this->streams_lock);
+#else
+ /*
+ * Ugly hack to avoid the above mentioned deadlock: try to
+ * release the streams_lock as soon as possible, when we know
+ * that the current stream is the last one.
+ *
+ * This hack only works when the stream with video_decorder_plugin
+ * is the last one in the streams list!
+ */
+ pthread_mutex_lock(&this->streams_lock);
+ if ((stream = xine_list_first_content(this->streams)) != NULL) {
+ xine_stream_t *stream_next;
+
+ for (; stream; stream = stream_next) {
+ stream_next = xine_list_next_content(this->streams);
+ if (!stream_next)
+ pthread_mutex_unlock(&this->streams_lock);
+
+ if (stream->video_decoder_plugin) {
+
+#ifdef LOG
+ printf ("video_out: flushing current video decoder plugin (%d %d)\n",
+ this->display_img_buf_queue->num_buffers,
+ this->free_img_buf_queue->num_buffers);
+#endif
+
+ stream->video_decoder_plugin->flush(stream->video_decoder_plugin);
+ }
+ }
+ } else
+ pthread_mutex_unlock(&this->streams_lock);
+#endif
+
this->last_delivery_pts = vpts;
}