<div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote">On Wed, Sep 24, 2014 at 8:06 PM, Jeremy White <span dir="ltr"><<a href="mailto:jwhite@codeweavers.com" target="_blank">jwhite@codeweavers.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">A MsgMainMultiMediaTime message on the main channel will be relayed<br>
through main_dispatcher so as to be fired in the context of the<br>
main (not worker) thread.<br>
<br>
In qemu, that thread happens to also be the thread that drives the<br>
audio channel, so it works.<br>
<br>
In XSpice, it is a different thread, which leads to unpleasant<br>
side effects.  The predominant side effect I noticed was an infinite loop<br>
in snd_send_data.<br></blockquote><div><br></div><div>Is this difficult to solve? It seems the thread is reading from a fd and pushing to spice server. Couldn't this be done from X main loop?<br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
This patch uses a mutex to prevent such collisions.<br></blockquote><div><br></div><div>Is the mutex supposed to protect the whole SndChannel struct?It seems there are various code path that could be called with or without the lock held (snd_playback_send callback, for example).  I would rather move the protected bits into a substructure, and make sure only access is made with the lock. <br><br></div><div>But I think we are going in a dangerous place if we start making spice server MT-safe api<br></div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<br>
Signed-off-by: Jeremy White <<a href="mailto:jwhite@codeweavers.com">jwhite@codeweavers.com</a>><br>
---<br>
 server/snd_worker.c |   30 ++++++++++++++++++++++++++++--<br>
 1 file changed, 28 insertions(+), 2 deletions(-)<br>
<br>
diff --git a/server/snd_worker.c b/server/snd_worker.c<br>
index 70148b7..b977bed 100644<br>
--- a/server/snd_worker.c<br>
+++ b/server/snd_worker.c<br>
@@ -115,6 +115,8 @@ struct SndChannel {<br>
     snd_channel_handle_message_proc handle_message;<br>
     snd_channel_on_message_done_proc on_message_done;<br>
     snd_channel_cleanup_channel_proc cleanup;<br>
+<br>
+    pthread_mutex_t lock;<br>
 };<br>
<br>
 typedef struct PlaybackChannel PlaybackChannel;<br>
@@ -220,8 +222,21 @@ static void snd_disconnect_channel(SndChannel *channel)<br>
     spice_marshaller_destroy(channel->send_data.marshaller);<br>
     snd_channel_put(channel);<br>
     worker->connection = NULL;<br>
+<br>
+    pthread_mutex_destroy(&channel->lock);<br>
+}<br>
+<br>
+static int snd_lock(SndChannel *channel)<br>
+{<br>
+    return pthread_mutex_lock(&channel->lock);<br>
+}<br>
+<br>
+static void snd_unlock(SndChannel *channel)<br>
+{<br>
+    pthread_mutex_unlock(&channel->lock);<br>
 }<br>
<br>
+<br>
 static void snd_playback_free_frame(PlaybackChannel *playback_channel, AudioFrame *frame)<br>
 {<br>
     frame->channel = playback_channel;<br>
@@ -967,6 +982,8 @@ static SndChannel *__new_channel(SndWorker *worker, int size, uint32_t channel_i<br>
     if (!channel->channel_client) {<br>
         goto error2;<br>
     }<br>
+<br>
+    pthread_mutex_init(&channel->lock, NULL);<br>
     return channel;<br>
<br>
 error2:<br>
@@ -1105,10 +1122,15 @@ SPICE_GNUC_VISIBLE void spice_server_playback_put_samples(SpicePlaybackInstance<br>
     frame = SPICE_CONTAINEROF(samples, AudioFrame, samples);<br>
     playback_channel = frame->channel;<br>
     spice_assert(playback_channel);<br>
+<br>
+    if (snd_lock(&playback_channel->base) != 0)<br>
+        return;<br>
+<br>
     if (!snd_channel_put(&playback_channel->base) ||<br>
         sin->st->worker.connection != &playback_channel->base) {<br>
         /* lost last reference, channel has been destroyed previously */<br>
         spice_info("audio samples belong to a disconnected channel");<br>
+        snd_unlock(&playback_channel->base);<br>
         return;<br>
     }<br>
     spice_assert(playback_channel->base.active);<br>
@@ -1121,6 +1143,7 @@ SPICE_GNUC_VISIBLE void spice_server_playback_put_samples(SpicePlaybackInstance<br>
     playback_channel->pending_frame = frame;<br>
     snd_set_command(&playback_channel->base, SND_PLAYBACK_PCM_MASK);<br>
     snd_playback_send(&playback_channel->base);<br>
+    snd_unlock(&playback_channel->base);<br>
 }<br>
<br>
 void snd_set_playback_latency(RedClient *client, uint32_t latency)<br>
@@ -1136,8 +1159,11 @@ void snd_set_playback_latency(RedClient *client, uint32_t latency)<br>
                 PlaybackChannel* playback = (PlaybackChannel*)now->connection;<br>
<br>
                 playback->latency = latency;<br>
-                snd_set_command(now->connection, SND_PLAYBACK_LATENCY_MASK);<br>
-                snd_playback_send(now->connection);<br>
+                if (snd_lock(now->connection) == 0) {<br>
+                    snd_set_command(now->connection, SND_PLAYBACK_LATENCY_MASK);<br>
+                    snd_playback_send(now->connection);<br>
+                    snd_unlock(now->connection);<br>
+                }<br>
             } else {<br>
                 spice_debug("client doesn't not support SPICE_PLAYBACK_CAP_LATENCY");<br>
             }<br>
<span class=""><font color="#888888">--<br>
1.7.10.4<br>
<br>
_______________________________________________<br>
Spice-devel mailing list<br>
<a href="mailto:Spice-devel@lists.freedesktop.org">Spice-devel@lists.freedesktop.org</a><br>
<a href="http://lists.freedesktop.org/mailman/listinfo/spice-devel" target="_blank">http://lists.freedesktop.org/mailman/listinfo/spice-devel</a><br>
</font></span></blockquote></div><br><br clear="all"><br>-- <br>Marc-André Lureau
</div></div>