From f366b3698b409405e1ee88476d1186f29fe14b06 Mon Sep 17 00:00:00 2001 From: Benoit Goby Date: Fri, 16 Mar 2012 14:50:07 -0700 Subject: [PATCH] adb: Don't synchronize with transport using sleep Services that cause adbd to reboot are currently implemented this way: write(fd, response) close(fd) sleep(1) exit(1) sleep(1) is necessary to leave time for the transport to transmit the response before the daemon exits. This is slow and unreliable. Instead, add a flag to the asocket to make it exit the daemon only after the socket is closed. Change-Id: I9df45ea6221f0d9b828703b9b2316a5d4fe59352 --- adb/adb.h | 5 +++++ adb/services.c | 13 ------------- adb/sockets.c | 14 ++++++++++++++ 3 files changed, 19 insertions(+), 13 deletions(-) diff --git a/adb/adb.h b/adb/adb.h index 85922bf80..03a7393a0 100644 --- a/adb/adb.h +++ b/adb/adb.h @@ -86,6 +86,11 @@ struct asocket { */ int closing; + /* flag: quit adbd when both ends close the + ** local service socket + */ + int exit_on_close; + /* the asocket we are connected to */ diff --git a/adb/services.c b/adb/services.c index 6bbd6f882..495a0830f 100644 --- a/adb/services.c +++ b/adb/services.c @@ -129,10 +129,6 @@ void restart_root_service(int fd, void *cookie) snprintf(buf, sizeof(buf), "restarting adbd as root\n"); writex(fd, buf, strlen(buf)); adb_close(fd); - - // quit, and init will restart us as root - sleep(1); - exit(1); } } @@ -154,10 +150,6 @@ void restart_tcp_service(int fd, void *cookie) snprintf(buf, sizeof(buf), "restarting in TCP mode port: %d\n", port); writex(fd, buf, strlen(buf)); adb_close(fd); - - // quit, and init will restart us in TCP mode - sleep(1); - exit(1); } void restart_usb_service(int fd, void *cookie) @@ -168,10 +160,6 @@ void restart_usb_service(int fd, void *cookie) snprintf(buf, sizeof(buf), "restarting in USB mode\n"); writex(fd, buf, strlen(buf)); adb_close(fd); - - // quit, and init will restart us in USB mode - sleep(1); - exit(1); } void reboot_service(int fd, void *arg) @@ -371,7 +359,6 @@ static void subproc_waiter_service(int fd, void *cookie) break; } } - usleep(100000); // poll every 0.1 sec } D("shell exited fd=%d of pid=%d err=%d\n", fd, pid, errno); if (SHELL_EXIT_NOTIFY_FD >=0) { diff --git a/adb/sockets.c b/adb/sockets.c index df223b133..ce3c65ef4 100644 --- a/adb/sockets.c +++ b/adb/sockets.c @@ -199,6 +199,8 @@ static void local_socket_close(asocket *s) static void local_socket_destroy(asocket *s) { apacket *p, *n; + int exit_on_close = s->exit_on_close; + D("LS(%d): destroying fde.fd=%d\n", s->id, s->fde.fd); /* IMPORTANT: the remove closes the fd @@ -214,6 +216,11 @@ static void local_socket_destroy(asocket *s) } remove_socket(s); free(s); + + if (exit_on_close) { + D("local_socket_destroy: exiting\n"); + exit(1); + } } @@ -418,6 +425,13 @@ asocket *create_local_service_socket(const char *name) s = create_local_socket(fd); D("LS(%d): bound to '%s' via %d\n", s->id, name, fd); + + if (!strcmp(name, "root:") || !strcmp(name, "usb:") || + !strcmp(name, "tcpip:")) { + D("LS(%d): enabling exit_on_close\n", s->id); + s->exit_on_close = 1; + } + return s; }