aboutsummaryrefslogtreecommitdiffstats
path: root/android
diff options
context:
space:
mode:
authorVladimir Chtchetkine <vchtchetkine@google.com>2011-01-20 11:22:32 -0800
committerVladimir Chtchetkine <vchtchetkine@google.com>2011-01-20 11:22:32 -0800
commit6ee1c4edbd30b7c7aff9d6e13793207278aa1660 (patch)
tree6b0c00f806dfb8432cb7468bc725f9698d6b617b /android
parenta228e1347525147daa619b99ad4f832b78788cd1 (diff)
downloadexternal_qemu-6ee1c4edbd30b7c7aff9d6e13793207278aa1660.zip
external_qemu-6ee1c4edbd30b7c7aff9d6e13793207278aa1660.tar.gz
external_qemu-6ee1c4edbd30b7c7aff9d6e13793207278aa1660.tar.bz2
Fix framebuffer and user events service disconnection bug.
FB and UE services overwrite the socket's read callbacks, making the console unavare of the fact that console client gets disconnected. As the result, console clients for FB and UE stays alive after UI has exited, making it impossible to attach another UI. To fix this, we add socket read callbacks to the FB and UE service that monitor the disconnection event and destroy their console clients on such events. Change-Id: I82e714f33ccc81bc04ca47eda6fbb8fab4a313f9
Diffstat (limited to 'android')
-rw-r--r--android/console.c16
-rw-r--r--android/framebuffer-core.c15
-rw-r--r--android/user-events-core.c6
3 files changed, 37 insertions, 0 deletions
diff --git a/android/console.c b/android/console.c
index 6f9e26b..4c3548a 100644
--- a/android/console.c
+++ b/android/console.c
@@ -2550,6 +2550,14 @@ do_create_framebuffer_service( ControlClient client, char* args )
return 0;
}
+void
+destroy_control_fb_client(void)
+{
+ if (framebuffer_client != NULL) {
+ control_client_destroy(framebuffer_client);
+ }
+}
+
static int
do_create_user_events_service( ControlClient client, char* args )
{
@@ -2575,6 +2583,14 @@ do_create_user_events_service( ControlClient client, char* args )
return 0;
}
+
+void
+destroy_control_ue_client(void)
+{
+ if (user_events_client != NULL) {
+ control_client_destroy(user_events_client);
+ }
+}
#endif // CONFIG_STANDALONE_CORE
static const CommandDefRec qemu_commands[] =
diff --git a/android/framebuffer-core.c b/android/framebuffer-core.c
index 978bfc0..3eb7665 100644
--- a/android/framebuffer-core.c
+++ b/android/framebuffer-core.c
@@ -136,6 +136,9 @@ fbupdatenotify_delete(FBUpdateNotify* desc)
}
}
+/* Implemented in android/console.c */
+extern void destroy_control_fb_client(void);
+
/*
* Asynchronous I/O callback launched when writing framebuffer notifications
* to the socket.
@@ -147,6 +150,15 @@ corefb_io_func(void* opaque, int fd, unsigned events)
{
CoreFramebuffer* core_fb = opaque;
+ if (events & LOOP_IO_READ) {
+ // We don't expect the UI client to write anything here, except when
+ // the client gets disconnected.
+ loopIo_dontWantWrite(&core_fb->io);
+ loopIo_dontWantRead(&core_fb->io);
+ destroy_control_fb_client();
+ return;
+ }
+
while (core_fb->fb_update_head != NULL) {
FBUpdateNotify* current_update = core_fb->fb_update_head;
// Lets continue writing of the current notification.
@@ -192,6 +204,9 @@ corefb_create(int sock, const char* protocol, QFrameBuffer* fb)
ret->sock = sock;
ret->looper = looper_newCore();
loopIo_init(&ret->io, ret->looper, sock, corefb_io_func, ret);
+ // Since we're overriding the read callback with our looper's I/O routine,
+ // we need to have set our read callback here to monitor disconnections.
+ loopIo_wantRead(&ret->io);
ret->fb = fb;
ret->fb_update_head = NULL;
ret->fb_update_tail = NULL;
diff --git a/android/user-events-core.c b/android/user-events-core.c
index a732791..3b97c00 100644
--- a/android/user-events-core.c
+++ b/android/user-events-core.c
@@ -57,6 +57,8 @@ struct CoreUserEvents {
};
};
+/* Implemented in android/console.c */
+extern void destroy_control_ue_client(void);
/*
* Asynchronous I/O callback launched when reading user events from the socket.
@@ -135,6 +137,10 @@ coreue_io_func(void* opaque, int fd, unsigned events)
break;
case ASYNC_ERROR:
loopIo_dontWantRead(&ue->io);
+ if (errno == ECONNRESET) {
+ // UI has exited. We need to destroy user event service.
+ destroy_control_ue_client();
+ }
break;
case ASYNC_NEED_MORE: