|
|
cd9d16 |
commit 22b626e28e9895cc65c1e2023323bda5138716dc
|
|
|
cd9d16 |
Author: Gerd Hoffmann <kraxel@redhat.com>
|
|
|
cd9d16 |
Date: Fri Sep 2 15:03:28 2011 +0200
|
|
|
cd9d16 |
|
|
|
cd9d16 |
spice: workaround a spice server bug.
|
|
|
cd9d16 |
|
|
|
cd9d16 |
spice server might call the channel_event callback from spice server
|
|
|
cd9d16 |
thread context. Detect that and aquire iothread lock if needed,
|
|
|
cd9d16 |
|
|
|
cd9d16 |
diff --git a/ui/spice-core.c b/ui/spice-core.c
|
|
|
cd9d16 |
index dba11f0..3cbc721 100644
|
|
|
cd9d16 |
--- a/ui/spice-core.c
|
|
|
cd9d16 |
+++ b/ui/spice-core.c
|
|
|
cd9d16 |
@@ -19,6 +19,7 @@
|
|
|
cd9d16 |
#include <spice-experimental.h>
|
|
|
cd9d16 |
|
|
|
cd9d16 |
#include <netdb.h>
|
|
|
cd9d16 |
+#include <pthread.h>
|
|
|
cd9d16 |
|
|
|
cd9d16 |
#include "qemu-common.h"
|
|
|
cd9d16 |
#include "qemu-spice.h"
|
|
|
cd9d16 |
@@ -44,6 +45,8 @@ static char *auth_passwd;
|
|
|
cd9d16 |
static time_t auth_expires = TIME_MAX;
|
|
|
cd9d16 |
int using_spice = 0;
|
|
|
cd9d16 |
|
|
|
cd9d16 |
+static pthread_t me;
|
|
|
cd9d16 |
+
|
|
|
cd9d16 |
struct SpiceTimer {
|
|
|
cd9d16 |
QEMUTimer *timer;
|
|
|
cd9d16 |
QTAILQ_ENTRY(SpiceTimer) next;
|
|
|
cd9d16 |
@@ -217,6 +220,20 @@ static void channel_event(int event, SpiceChannelEventInfo *info)
|
|
|
cd9d16 |
QDict *server, *client;
|
|
|
cd9d16 |
QObject *data;
|
|
|
cd9d16 |
|
|
|
cd9d16 |
+ /*
|
|
|
cd9d16 |
+ * Spice server might have called us from spice worker thread
|
|
|
cd9d16 |
+ * context (happens on display channel disconnects). Spice should
|
|
|
cd9d16 |
+ * not do that. It isn't that easy to fix it in spice and even
|
|
|
cd9d16 |
+ * when it is fixed we still should cover the already released
|
|
|
cd9d16 |
+ * spice versions. So detect that we've been called from another
|
|
|
cd9d16 |
+ * thread and grab the iothread lock if so before calling qemu
|
|
|
cd9d16 |
+ * functions.
|
|
|
cd9d16 |
+ */
|
|
|
cd9d16 |
+ bool need_lock = !pthread_equal(me, pthread_self());
|
|
|
cd9d16 |
+ if (need_lock) {
|
|
|
cd9d16 |
+ qemu_mutex_lock_iothread();
|
|
|
cd9d16 |
+ }
|
|
|
cd9d16 |
+
|
|
|
cd9d16 |
client = qdict_new();
|
|
|
cd9d16 |
add_addr_info(client, &info->paddr, info->plen);
|
|
|
cd9d16 |
|
|
|
cd9d16 |
@@ -236,6 +253,10 @@ static void channel_event(int event, SpiceChannelEventInfo *info)
|
|
|
cd9d16 |
QOBJECT(client), QOBJECT(server));
|
|
|
cd9d16 |
monitor_protocol_event(qevent[event], data);
|
|
|
cd9d16 |
qobject_decref(data);
|
|
|
cd9d16 |
+
|
|
|
cd9d16 |
+ if (need_lock) {
|
|
|
cd9d16 |
+ qemu_mutex_unlock_iothread();
|
|
|
cd9d16 |
+ }
|
|
|
cd9d16 |
}
|
|
|
cd9d16 |
|
|
|
cd9d16 |
#else /* SPICE_INTERFACE_CORE_MINOR >= 3 */
|
|
|
cd9d16 |
@@ -482,7 +503,9 @@ void qemu_spice_init(void)
|
|
|
cd9d16 |
spice_image_compression_t compression;
|
|
|
cd9d16 |
spice_wan_compression_t wan_compr;
|
|
|
cd9d16 |
|
|
|
cd9d16 |
- if (!opts) {
|
|
|
cd9d16 |
+ me = pthread_self();
|
|
|
cd9d16 |
+
|
|
|
cd9d16 |
+ if (!opts) {
|
|
|
cd9d16 |
return;
|
|
|
cd9d16 |
}
|
|
|
cd9d16 |
port = qemu_opt_get_number(opts, "port", 0);
|