diff options
author | Reinhard Nißl <rnissl@gmx.de> | 2009-01-10 22:08:15 +0100 |
---|---|---|
committer | Reinhard Nißl <rnissl@gmx.de> | 2009-01-10 22:08:15 +0100 |
commit | 2a4f6f520b36d548960ade7c4d80162a0b6af224 (patch) | |
tree | ea6cd1fe80c75a270e84b58cb3a9792e6580d722 | |
parent | 8619a3368fb968b6416025e11009a09268352987 (diff) | |
download | xine-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.h | 1 | ||||
-rw-r--r-- | src/vdr/input_vdr.c | 17 |
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) { |