summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorIan Rae <irae@real.com>2009-09-14 10:01:43 -0700
committerIan Rae <irae@real.com>2009-09-14 10:01:43 -0700
commit2241baa294539a33d8bc6137e633bb4c93c22b4e (patch)
tree34ca8949c179ee9babd14d14976fb2fe0ceb6679 /src
parent9fe31f395320f8b41b7cad84d7f308a3091251a3 (diff)
downloadxine-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.c32
-rw-r--r--src/xine-engine/io_helper.c4
-rw-r--r--src/xine-engine/video_decoder.c2
-rw-r--r--src/xine-engine/xine.c6
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);