[Spice-devel] [PATCH spice-server 3/3] red_worker: disconnect the channel instead of shutdown in case of a blocking method failure

Yonit Halperin yhalperi at redhat.com
Thu Sep 26 10:59:58 PDT 2013


rhbz#1004443

The methods that trigger waitings on the client pipe require that
the waiting will succeed in order to continue, or otherwise, that
all the living pipe items will be released (e.g., when
we must destroy a surface, we need that all its related pipe items will
be released). Shutdown of the socket will eventually trigger
red_channel_client_disconnect (*), which will empty the pipe. However,
if the blocking method failed, we need to empty the pipe synchronously.
It is not safe(**) to call red_channel_client_disconnect from ChannelCbs
, but all the blocking calls in red_worker are done from callbacks that
are triggered from the device.
To summarize, calling red_channel_client_disconnect instead of calling
red_channel_client_shutdown will immediately release all the pipe items that are
held by the channel client (by calling red_channel_client_pipe_clear).
If red_clear_surface_drawables_from_pipe timeouts,
red_channel_client_disconnect will make sure that the surface we wish to
release is not referenced by any pipe-item.

(*) After a shutdown of a socket, we expect that later, when
red_peer_handle_incoming is called, it will encounter a socket
error and will call the channel's on_error callback which calls
red_channel_client_disconnect.

(**) I believe it was not safe before commit 2d2121a17038bc0 (before adding ref
count to ChannelClient). However, I think it might still be unsafe, because
red_channel_client_disconnect sets rcc->stream to NULL, and rcc->stream
may be referred later inside a red_channel_client method unsafely. So instead
of checking if (stream != NULL) after calling callbacks, we try to avoid
calling red_channel_client_disconnect from callbacks.
---
 server/red_worker.c | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/server/red_worker.c b/server/red_worker.c
index dea7325..1f67212 100644
--- a/server/red_worker.c
+++ b/server/red_worker.c
@@ -10959,10 +10959,10 @@ void handle_dev_destroy_surface_wait(void *opaque, void *payload)
     dev_destroy_surface_wait(worker, msg->surface_id);
 }
 
-static void rcc_shutdown_if_pending_send(RedChannelClient *rcc)
+static void rcc_disconnect_if_pending_send(RedChannelClient *rcc)
 {
     if (red_channel_client_blocked(rcc) || rcc->pipe_size > 0) {
-        red_channel_client_shutdown(rcc);
+        red_channel_client_disconnect(rcc);
     } else {
         spice_assert(red_channel_client_no_item_being_sent(rcc));
     }
@@ -10988,7 +10988,7 @@ static inline void red_cursor_reset(RedWorker *worker)
         if (!red_channel_wait_all_sent(&worker->cursor_channel->common.base,
                                        DISPLAY_CLIENT_TIMEOUT)) {
             red_channel_apply_clients(&worker->cursor_channel->common.base,
-                                      rcc_shutdown_if_pending_send);
+                                      rcc_disconnect_if_pending_send);
         }
     }
 }
@@ -11275,12 +11275,12 @@ void handle_dev_stop(void *opaque, void *payload)
     if (!red_channel_wait_all_sent(&worker->display_channel->common.base,
                                    DISPLAY_CLIENT_TIMEOUT)) {
         red_channel_apply_clients(&worker->display_channel->common.base,
-                                  rcc_shutdown_if_pending_send);
+                                  rcc_disconnect_if_pending_send);
     }
     if (!red_channel_wait_all_sent(&worker->cursor_channel->common.base,
                                    DISPLAY_CLIENT_TIMEOUT)) {
         red_channel_apply_clients(&worker->cursor_channel->common.base,
-                                  rcc_shutdown_if_pending_send);
+                                  rcc_disconnect_if_pending_send);
     }
 }
 
-- 
1.8.1.4



More information about the Spice-devel mailing list