summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorReinhard Nißl <rnissl@gmx.de>2009-01-10 22:08:15 +0100
committerReinhard Nißl <rnissl@gmx.de>2009-01-10 22:08:15 +0100
commit2a4f6f520b36d548960ade7c4d80162a0b6af224 (patch)
treeea6cd1fe80c75a270e84b58cb3a9792e6580d722
parent8619a3368fb968b6416025e11009a09268352987 (diff)
downloadxine-lib-2a4f6f520b36d548960ade7c4d80162a0b6af224.tar.gz
xine-lib-2a4f6f520b36d548960ade7c4d80162a0b6af224.tar.bz2
Fix locking issues in startup phase which could lead to disconnects.
input_vdr's RPC thread needs to lock frontend. But frontend is also locked during xine_open() and xine_play(). xine_play() furthermore waits up to 10 seconds for the decoder to return the first frame. So it is unlikely that the RPC thread can lock the frontend to execute VDR's commands before VDR sends the first frame. Finally the RPC thread gave up locking the frontend after 5 seconds and the connect to VDR failed. To fix this issue, the RPC commands during startup phase are now handled by the thread which has called xine_open() as it already owns the frontend lock.
-rw-r--r--include/xine/vdr.h1
-rw-r--r--src/vdr/input_vdr.c17
2 files changed, 17 insertions, 1 deletions
diff --git a/include/xine/vdr.h b/include/xine/vdr.h
index 392d1e404..1f253cdbe 100644
--- a/include/xine/vdr.h
+++ b/include/xine/vdr.h
@@ -343,6 +343,7 @@ data_start_t;
typedef struct __attribute__((packed)) data_wait_s
{
data_header_t header;
+ uint8_t id;
}
data_wait_t;
diff --git a/src/vdr/input_vdr.c b/src/vdr/input_vdr.c
index b2dea3864..3898acdc6 100644
--- a/src/vdr/input_vdr.c
+++ b/src/vdr/input_vdr.c
@@ -124,6 +124,7 @@ struct vdr_input_plugin_s
int rpc_thread_shutdown;
pthread_mutex_t rpc_thread_shutdown_lock;
pthread_cond_t rpc_thread_shutdown_cond;
+ int startup_phase;
xine_event_queue_t *event_queue;
xine_event_queue_t *event_queue_external;
@@ -992,6 +993,9 @@ fprintf(stderr, "--- CLEAR(%d%c)\n", data->n, data->s ? 'b' : 'a');
if (sizeof (result_wait) != vdr_write(this->fh_result, &result_wait, sizeof (result_wait)))
return -1;
+
+ if (data->id == 1)
+ this->startup_phase = 0;
}
}
break;
@@ -1259,9 +1263,11 @@ static void *vdr_rpc_thread_loop(void *arg)
vdr_input_plugin_t *this = (vdr_input_plugin_t *)arg;
int frontend_lock_failures = 0;
int failed = 0;
+ int was_startup_phase = this->startup_phase;
while (!failed
- && !this->rpc_thread_shutdown)
+ && !this->rpc_thread_shutdown
+ && was_startup_phase == this->startup_phase)
{
struct timeval timeout;
fd_set rset;
@@ -1304,6 +1310,9 @@ static void *vdr_rpc_thread_loop(void *arg)
}
}
+ if (!failed && was_startup_phase)
+ return (void *)1;
+
/* close control and result channel here to have vdr-xine initiate a disconnect for the above error case ... */
close(this->fh_control);
this->fh_control = -1;
@@ -1947,6 +1956,12 @@ static int vdr_plugin_open(input_plugin_t *this_gen)
}
this->rpc_thread_shutdown = 0;
+
+ /* let this thread handle rpc commands in startup phase */
+ this->startup_phase = 1;
+ if (0 == vdr_rpc_thread_loop(this))
+ return 0;
+
if ((err = pthread_create(&this->rpc_thread, NULL,
vdr_rpc_thread_loop, (void *)this)) != 0)
{