spice: workaround a spice server bug.
spice server might call the channel_event callback from spice server thread context. Detect that and aquire iothread lock if needed,
This commit is contained in:
		
							parent
							
								
									7e79cf4083
								
							
						
					
					
						commit
						22b626e28e
					
				@ -19,6 +19,7 @@
 | 
				
			|||||||
#include <spice-experimental.h>
 | 
					#include <spice-experimental.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <netdb.h>
 | 
					#include <netdb.h>
 | 
				
			||||||
 | 
					#include <pthread.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "qemu-common.h"
 | 
					#include "qemu-common.h"
 | 
				
			||||||
#include "qemu-spice.h"
 | 
					#include "qemu-spice.h"
 | 
				
			||||||
@ -44,6 +45,8 @@ static char *auth_passwd;
 | 
				
			|||||||
static time_t auth_expires = TIME_MAX;
 | 
					static time_t auth_expires = TIME_MAX;
 | 
				
			||||||
int using_spice = 0;
 | 
					int using_spice = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static pthread_t me;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct SpiceTimer {
 | 
					struct SpiceTimer {
 | 
				
			||||||
    QEMUTimer *timer;
 | 
					    QEMUTimer *timer;
 | 
				
			||||||
    QTAILQ_ENTRY(SpiceTimer) next;
 | 
					    QTAILQ_ENTRY(SpiceTimer) next;
 | 
				
			||||||
@ -217,6 +220,20 @@ static void channel_event(int event, SpiceChannelEventInfo *info)
 | 
				
			|||||||
    QDict *server, *client;
 | 
					    QDict *server, *client;
 | 
				
			||||||
    QObject *data;
 | 
					    QObject *data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /*
 | 
				
			||||||
 | 
					     * Spice server might have called us from spice worker thread
 | 
				
			||||||
 | 
					     * context (happens on display channel disconnects).  Spice should
 | 
				
			||||||
 | 
					     * not do that.  It isn't that easy to fix it in spice and even
 | 
				
			||||||
 | 
					     * when it is fixed we still should cover the already released
 | 
				
			||||||
 | 
					     * spice versions.  So detect that we've been called from another
 | 
				
			||||||
 | 
					     * thread and grab the iothread lock if so before calling qemu
 | 
				
			||||||
 | 
					     * functions.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    bool need_lock = !pthread_equal(me, pthread_self());
 | 
				
			||||||
 | 
					    if (need_lock) {
 | 
				
			||||||
 | 
					        qemu_mutex_lock_iothread();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    client = qdict_new();
 | 
					    client = qdict_new();
 | 
				
			||||||
    add_addr_info(client, &info->paddr, info->plen);
 | 
					    add_addr_info(client, &info->paddr, info->plen);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -236,6 +253,10 @@ static void channel_event(int event, SpiceChannelEventInfo *info)
 | 
				
			|||||||
                              QOBJECT(client), QOBJECT(server));
 | 
					                              QOBJECT(client), QOBJECT(server));
 | 
				
			||||||
    monitor_protocol_event(qevent[event], data);
 | 
					    monitor_protocol_event(qevent[event], data);
 | 
				
			||||||
    qobject_decref(data);
 | 
					    qobject_decref(data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (need_lock) {
 | 
				
			||||||
 | 
					        qemu_mutex_unlock_iothread();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#else /* SPICE_INTERFACE_CORE_MINOR >= 3 */
 | 
					#else /* SPICE_INTERFACE_CORE_MINOR >= 3 */
 | 
				
			||||||
@ -482,6 +503,8 @@ void qemu_spice_init(void)
 | 
				
			|||||||
    spice_image_compression_t compression;
 | 
					    spice_image_compression_t compression;
 | 
				
			||||||
    spice_wan_compression_t wan_compr;
 | 
					    spice_wan_compression_t wan_compr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    me = pthread_self();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
   if (!opts) {
 | 
					   if (!opts) {
 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user