diff options
author | Juergen Keil <jkeil@users.sourceforge.net> | 2002-12-20 18:14:34 +0000 |
---|---|---|
committer | Juergen Keil <jkeil@users.sourceforge.net> | 2002-12-20 18:14:34 +0000 |
commit | b8019d2a215ba08c34997ab9314b658245ef363f (patch) | |
tree | f4163258406e628d8ee98c17b9de34ea9cedb1b2 | |
parent | e315d1402cf9988403047f091964e940e1ee8b68 (diff) | |
download | xine-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.c | 48 |
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; } |