[Spice-devel] [Xspice 1/2] spiceqxl_audio: Fix a race condition in the audio playback
Francois Gouget
fgouget at codeweavers.com
Mon Mar 14 18:10:40 UTC 2016
can_feed() depends on the time and thus could return false in
process_fifos(), causing it to stop reading from the fifos, and then
true in watch_or_wait() so that the wall_timer would not be set, but
the fifos would not be watched either because they already contain
data to process. The audio playback would then come to a stop.
Signed-off-by: Francois Gouget <fgouget at codeweavers.com>
---
src/spiceqxl_audio.c | 39 +++++++++++++++++----------------------
1 file changed, 17 insertions(+), 22 deletions(-)
diff --git a/src/spiceqxl_audio.c b/src/spiceqxl_audio.c
index eba9b10..1aebe8d 100644
--- a/src/spiceqxl_audio.c
+++ b/src/spiceqxl_audio.c
@@ -146,6 +146,7 @@ static void mix_in_one_fifo(struct fifo_data *f, int16_t *out, int len)
free(in);
}
+/* a helper for process_fifos() */
static void mix_in_fifos(qxl_screen_t *qxl)
{
int i;
@@ -169,6 +170,7 @@ static void mix_in_fifos(qxl_screen_t *qxl)
}
}
+/* a helper for process_fifos() */
static int can_feed(struct audio_data *data)
{
struct timeval end, diff;
@@ -190,6 +192,7 @@ static int can_feed(struct audio_data *data)
return 0;
}
+/* a helper for process_fifos() */
static void did_feed(struct audio_data *data, int len)
{
struct timeval diff;
@@ -223,7 +226,7 @@ static void condense_fifos(struct audio_data *data)
}
}
-static void watch_or_wait(qxl_screen_t *qxl);
+static void start_watching(qxl_screen_t *qxl);
static void process_fifos(qxl_screen_t *qxl, struct audio_data *data, int maxlen)
{
while (maxlen > 0) {
@@ -236,8 +239,13 @@ static void process_fifos(qxl_screen_t *qxl, struct audio_data *data, int maxlen
if (! data->spice_buffer)
break;
- if (! can_feed(data))
- break;
+ if (! can_feed(data)) {
+ if (! data->wall_timer_live) {
+ qxl->core->timer_start(data->wall_timer, PERIOD_MS);
+ data->wall_timer_live++;
+ }
+ return;
+ }
mix_in_fifos(qxl);
@@ -248,7 +256,11 @@ static void process_fifos(qxl_screen_t *qxl, struct audio_data *data, int maxlen
data->spice_buffer = NULL;
}
- watch_or_wait(qxl);
+ start_watching(qxl);
+ if (data->wall_timer_live) {
+ qxl->core->timer_cancel(data->wall_timer);
+ }
+ data->wall_timer_live = 0;
}
static void read_from_fifos(int fd, int event, void *opaque)
@@ -293,6 +305,7 @@ static void read_from_fifos(int fd, int event, void *opaque)
process_fifos(qxl, data, maxlen);
}
+/* a helper for process_fifos() */
static void start_watching(qxl_screen_t *qxl)
{
struct audio_data *data = qxl->playback_opaque;
@@ -307,24 +320,6 @@ static void start_watching(qxl_screen_t *qxl)
}
}
-static void watch_or_wait(qxl_screen_t *qxl)
-{
- struct audio_data *data = qxl->playback_opaque;
-
- if (! can_feed(data)) {
- if (! data->wall_timer_live) {
- qxl->core->timer_start(data->wall_timer, PERIOD_MS);
- data->wall_timer_live++;
- }
- }
- else {
- start_watching(qxl);
- if (data->wall_timer_live)
- qxl->core->timer_cancel(data->wall_timer);
- data->wall_timer_live = 0;
- }
-}
-
static void wall_ticker(void *opaque)
{
qxl_screen_t *qxl = opaque;
--
2.7.0
More information about the Spice-devel
mailing list