diff options
author | Ian Rae <irae@real.com> | 2009-09-14 10:01:43 -0700 |
---|---|---|
committer | Ian Rae <irae@real.com> | 2009-09-14 10:01:43 -0700 |
commit | 2241baa294539a33d8bc6137e633bb4c93c22b4e (patch) | |
tree | 34ca8949c179ee9babd14d14976fb2fe0ceb6679 /src | |
parent | 9fe31f395320f8b41b7cad84d7f308a3091251a3 (diff) | |
download | xine-lib-2241baa294539a33d8bc6137e633bb4c93c22b4e.tar.gz xine-lib-2241baa294539a33d8bc6137e633bb4c93c22b4e.tar.bz2 |
Protected access to stream->demux_action_pending
The deadlock was caused by the unprotected use of
stream->demux_action_pending internal variable from play_internal() and from
within the demuxer loop.
Direct access to demux_action_pending is replaced with _x_action_raise() and
_x_action_lower(), which use a mutex for thread safety.
Diffstat (limited to 'src')
-rw-r--r-- | src/xine-engine/demux.c | 32 | ||||
-rw-r--r-- | src/xine-engine/io_helper.c | 4 | ||||
-rw-r--r-- | src/xine-engine/video_decoder.c | 2 | ||||
-rw-r--r-- | src/xine-engine/xine.c | 6 |
4 files changed, 31 insertions, 13 deletions
diff --git a/src/xine-engine/demux.c b/src/xine-engine/demux.c index f7db28e2b..0321d7404 100644 --- a/src/xine-engine/demux.c +++ b/src/xine-engine/demux.c @@ -200,7 +200,7 @@ void _x_demux_control_headers_done (xine_stream_t *stream) { buf_element_t *buf_video, *buf_audio; /* we use demux_action_pending to wake up sleeping spu decoders */ - stream->demux_action_pending = 1; + _x_action_raise(stream); /* allocate the buffers before grabbing the lock to prevent cyclic wait situations */ buf_video = stream->video_fifo->buffer_pool_alloc (stream->video_fifo); @@ -252,7 +252,7 @@ void _x_demux_control_headers_done (xine_stream_t *stream) { } } - stream->demux_action_pending = 0; + _x_action_lower(stream); pthread_cond_signal(&stream->demux_resume); lprintf ("headers processed.\n"); @@ -342,7 +342,7 @@ static void *demux_loop (void *stream_gen) { status = stream->demux_plugin->send_chunk(stream->demux_plugin); /* someone may want to interrupt us */ - if( stream->demux_action_pending ) { + if (_x_action_pending(stream)) { struct timeval tv; struct timespec ts; @@ -434,9 +434,9 @@ int _x_demux_start_thread (xine_stream_t *stream) { lprintf ("start thread called\n"); - stream->demux_action_pending = 1; + _x_action_raise(stream); pthread_mutex_lock( &stream->demux_lock ); - stream->demux_action_pending = 0; + _x_action_lower(stream); pthread_cond_signal(&stream->demux_resume); if( !stream->demux_thread_running ) { @@ -465,10 +465,10 @@ int _x_demux_stop_thread (xine_stream_t *stream) { lprintf ("stop thread called\n"); - stream->demux_action_pending = 1; + _x_action_raise(stream); pthread_mutex_lock( &stream->demux_lock ); stream->demux_thread_running = 0; - stream->demux_action_pending = 0; + _x_action_lower(stream); pthread_cond_signal(&stream->demux_resume); /* At that point, the demuxer has sent the last audio/video buffer, @@ -585,7 +585,7 @@ off_t _x_read_abort (xine_stream_t *stream, int fd, char *buf, off_t todo) { /* aborts current read if action pending. otherwise xine * cannot be stopped when no more data is available. */ - if( stream->demux_action_pending ) + if (_x_action_pending(stream)) return total; } else { break; @@ -626,6 +626,22 @@ int _x_action_pending (xine_stream_t *stream) { return stream->demux_action_pending; } +/* set demux_action_pending in a thread-safe way */ +void _x_action_raise (xine_stream_t *stream) +{ + pthread_mutex_lock(&stream->demux_action_lock); + stream->demux_action_pending++; + pthread_mutex_unlock(&stream->demux_action_lock); +} + +/* reset demux_action_pending in a thread-safe way */ +void _x_action_lower (xine_stream_t *stream) +{ + pthread_mutex_lock(&stream->demux_action_lock); + stream->demux_action_pending--; + pthread_mutex_unlock(&stream->demux_action_lock); +} + /* * demuxer helper function to send data to fifo, breaking into smaller * pieces (bufs) as needed. diff --git a/src/xine-engine/io_helper.c b/src/xine-engine/io_helper.c index 34540a208..d331b675a 100644 --- a/src/xine-engine/io_helper.c +++ b/src/xine-engine/io_helper.c @@ -244,7 +244,7 @@ int _x_io_select (xine_stream_t *stream, int fd, int state, int timeout_msec) { * aborts current read if action pending. otherwise xine * cannot be stopped when no more data is available. */ - if (stream && stream->demux_action_pending) + if (stream && _x_action_pending(stream)) return XIO_ABORTED; break; case WAIT_ABANDONED: @@ -288,7 +288,7 @@ int _x_io_select (xine_stream_t *stream, int fd, int state, int timeout_msec) { * aborts current read if action pending. otherwise xine * cannot be stopped when no more data is available. */ - if (stream && stream->demux_action_pending) + if (stream && _x_action_pending(stream)) return XIO_ABORTED; total_time_usec += XIO_POLLING_INTERVAL; diff --git a/src/xine-engine/video_decoder.c b/src/xine-engine/video_decoder.c index ed2e41ef3..c548d12ef 100644 --- a/src/xine-engine/video_decoder.c +++ b/src/xine-engine/video_decoder.c @@ -92,7 +92,7 @@ int _x_spu_decoder_sleep(xine_stream_t *stream, int64_t next_spu_vpts) thread_vacant = (stream->video_fifo->first->type != BUF_CONTROL_FLUSH_DECODER); /* we have to return if the demuxer needs us to release a buffer */ if (thread_vacant) - thread_vacant = !stream->demux_action_pending; + thread_vacant = !_x_action_pending(stream); } while (wait == SPU_SLEEP_INTERVAL && thread_vacant); diff --git a/src/xine-engine/xine.c b/src/xine-engine/xine.c index 29b4b3543..31b1f254d 100644 --- a/src/xine-engine/xine.c +++ b/src/xine-engine/xine.c @@ -679,6 +679,7 @@ xine_stream_t *xine_stream_new (xine_t *this, pthread_mutex_init (&stream->info_mutex, NULL); pthread_mutex_init (&stream->meta_mutex, NULL); pthread_mutex_init (&stream->demux_lock, NULL); + pthread_mutex_init (&stream->demux_action_lock, NULL); pthread_mutex_init (&stream->demux_mutex, NULL); pthread_cond_init (&stream->demux_resume, NULL); pthread_mutex_init (&stream->event_queues_lock, NULL); @@ -1378,7 +1379,7 @@ static int play_internal (xine_stream_t *stream, int start_pos, int start_time) } /* hint demuxer thread we want to interrupt it */ - stream->demux_action_pending = 1; + _x_action_raise(stream); /* set normal speed */ if (_x_get_speed(stream) != XINE_SPEED_NORMAL) @@ -1397,7 +1398,7 @@ static int play_internal (xine_stream_t *stream, int start_pos, int start_time) pthread_mutex_lock( &stream->demux_lock ); /* demux_lock taken. now demuxer is suspended */ - stream->demux_action_pending = 0; + _x_action_lower(stream); pthread_cond_signal(&stream->demux_resume); /* set normal speed again (now that demuxer/input pair is suspended) @@ -1526,6 +1527,7 @@ static void xine_dispose_internal (xine_stream_t *stream) { pthread_cond_destroy (&stream->counter_changed); pthread_mutex_destroy (&stream->demux_mutex); pthread_cond_destroy (&stream->demux_resume); + pthread_mutex_destroy (&stream->demux_action_lock); pthread_mutex_destroy (&stream->demux_lock); pthread_mutex_destroy (&stream->first_frame_lock); pthread_cond_destroy (&stream->first_frame_reached); |