summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArnon Gilboa <agilboa@redhat.com>2013-01-31 11:17:40 +0200
committerArnon Gilboa <agilboa@redhat.com>2013-01-31 11:34:14 +0200
commit2d03cc5c2c8cf4e6acccdb7906af7ae61e97d47c (patch)
tree5acd0c57eda82b3f65407ba1aeb4d15ca508cd4a
parent05af7a9786507cd729cb7505e5b103b47aa29852 (diff)
vdservice stops vdagent via event
Terminate agent politely instead of ugly TerminateProcess(), so now VD_AGENT_CLIPBOARD_RELEASE is sent (if guest owned the clipboard), followed by cleanup. rhbz #903379
-rw-r--r--common/vdcommon.h1
-rw-r--r--vdagent/vdagent.cpp16
-rw-r--r--vdservice/vdservice.cpp5
3 files changed, 20 insertions, 2 deletions
diff --git a/common/vdcommon.h b/common/vdcommon.h
index cc3bd3d..605153d 100644
--- a/common/vdcommon.h
+++ b/common/vdcommon.h
@@ -33,6 +33,7 @@ typedef CRITICAL_SECTION mutex_t;
#define MUTEX_UNLOCK(mutex) LeaveCriticalSection(&mutex)
#define VD_AGENT_REGISTRY_KEY "SOFTWARE\\Red Hat\\Spice\\vdagent\\"
+#define VD_AGENT_STOP_EVENT TEXT("Global\\vdagent_stop_event")
#if defined __GNUC__
#define ALIGN_GCC __attribute__ ((packed))
diff --git a/vdagent/vdagent.cpp b/vdagent/vdagent.cpp
index 85244c0..722815c 100644
--- a/vdagent/vdagent.cpp
+++ b/vdagent/vdagent.cpp
@@ -128,6 +128,7 @@ private:
INPUT _input;
DWORD _input_time;
HANDLE _control_event;
+ HANDLE _stop_event;
VDAgentMessage* _in_msg;
uint32_t _in_msg_pos;
bool _pending_input;
@@ -180,6 +181,7 @@ VDAgent::VDAgent()
, _mouse_y (0)
, _input_time (0)
, _control_event (NULL)
+ , _stop_event (NULL)
, _in_msg (NULL)
, _in_msg_pos (0)
, _pending_input (false)
@@ -266,6 +268,12 @@ bool VDAgent::run()
cleanup();
return false;
}
+ _stop_event = OpenEvent(SYNCHRONIZE, FALSE, VD_AGENT_STOP_EVENT);
+ if (!_stop_event) {
+ vd_printf("OpenEvent() failed: %lu", GetLastError());
+ cleanup();
+ return false;
+ }
memset(&wcls, 0, sizeof(wcls));
wcls.lpfnWndProc = &VDAgent::wnd_proc;
wcls.lpszClassName = VD_AGENT_WINCLASS_NAME;
@@ -312,6 +320,7 @@ bool VDAgent::run()
void VDAgent::cleanup()
{
+ CloseHandle(_stop_event);
CloseHandle(_control_event);
CloseHandle(_vio_serial);
delete _desktop_layout;
@@ -428,15 +437,20 @@ void VDAgent::input_desktop_message_loop()
void VDAgent::event_dispatcher(DWORD timeout, DWORD wake_mask)
{
+ HANDLE events[] = {_control_event, _stop_event};
+ const DWORD event_count = sizeof(events) / sizeof(events[0]);
DWORD wait_ret;
MSG msg;
- wait_ret = MsgWaitForMultipleObjectsEx(1, &_control_event, timeout, wake_mask, MWMO_ALERTABLE);
+ wait_ret = MsgWaitForMultipleObjectsEx(event_count, events, timeout, wake_mask, MWMO_ALERTABLE);
switch (wait_ret) {
case WAIT_OBJECT_0:
handle_control_event();
break;
case WAIT_OBJECT_0 + 1:
+ _running = false;
+ break;
+ case WAIT_OBJECT_0 + event_count:
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
diff --git a/vdservice/vdservice.cpp b/vdservice/vdservice.cpp
index a2cf67d..a899ae1 100644
--- a/vdservice/vdservice.cpp
+++ b/vdservice/vdservice.cpp
@@ -92,6 +92,7 @@ private:
SERVICE_STATUS_HANDLE _status_handle;
PROCESS_INFORMATION _agent_proc_info;
HANDLE _control_event;
+ HANDLE _agent_stop_event;
HANDLE* _events;
TCHAR _agent_path[MAX_PATH];
VDControlQueue _control_queue;
@@ -157,6 +158,7 @@ VDService::VDService()
ZeroMemory(&_agent_proc_info, sizeof(_agent_proc_info));
_system_version = supported_system_version();
_control_event = CreateEvent(NULL, FALSE, FALSE, NULL);
+ _agent_stop_event = CreateEvent(NULL, FALSE, FALSE, VD_AGENT_STOP_EVENT);
_agent_path[0] = wchar_t('\0');
MUTEX_INIT(_agent_mutex);
MUTEX_INIT(_control_mutex);
@@ -165,6 +167,7 @@ VDService::VDService()
VDService::~VDService()
{
+ CloseHandle(_agent_stop_event);
CloseHandle(_control_event);
delete _events;
delete _log;
@@ -777,7 +780,7 @@ bool VDService::kill_agent()
_agent_alive = false;
proc_handle = _agent_proc_info.hProcess;
_agent_proc_info.hProcess = 0;
- TerminateProcess(proc_handle, 0);
+ SetEvent(_agent_stop_event);
if (GetProcessId(proc_handle)) {
wait_ret = WaitForSingleObject(proc_handle, VD_AGENT_TIMEOUT);
switch (wait_ret) {