summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMike Lockwood2009-07-30 18:23:56 -0500
committerMike Lockwood2009-07-30 18:23:56 -0500
commitcc1de48dcdf06c76ee14abbe2a237aa51b5b3bad (patch)
tree4b224a4d8b3493cecc32e23cb589cfde77c6825a
parentde6f62a609120c3d9e4e53689c3b309842ec874b (diff)
downloadplatform-system-core-cc1de48dcdf06c76ee14abbe2a237aa51b5b3bad.tar.gz
platform-system-core-cc1de48dcdf06c76ee14abbe2a237aa51b5b3bad.tar.xz
platform-system-core-cc1de48dcdf06c76ee14abbe2a237aa51b5b3bad.zip
adb: Another attempted workaround for the adb disconnect problem.
For adb shell commands (as well as shell based commands like logcat and bugreport) we now batch USB writes into 4K chunks instead of sending small packets of data as they come in. A timeout prevents us from blocking for more than 100ms when our 4K buffer is partially full. Signed-off-by: Mike Lockwood <lockwood@android.com>
-rw-r--r--adb/services.c92
1 files changed, 81 insertions, 11 deletions
diff --git a/adb/services.c b/adb/services.c
index 0a5edcf4b..78d092b83 100644
--- a/adb/services.c
+++ b/adb/services.c
@@ -31,6 +31,8 @@
31# include <netinet/in.h> 31# include <netinet/in.h>
32# include <netdb.h> 32# include <netdb.h>
33# endif 33# endif
34#else
35#include <sys/poll.h>
34#endif 36#endif
35 37
36typedef struct stinfo stinfo; 38typedef struct stinfo stinfo;
@@ -196,12 +198,9 @@ static int create_service_thread(void (*func)(int, void *), void *cookie)
196 return s[0]; 198 return s[0];
197} 199}
198 200
201#if !ADB_HOST
199static int create_subprocess(const char *cmd, const char *arg0, const char *arg1) 202static int create_subprocess(const char *cmd, const char *arg0, const char *arg1)
200{ 203{
201#ifdef HAVE_WIN32_PROC
202 fprintf(stderr, "error: create_subprocess not implemented on Win32 (%s %s %s)\n", cmd, arg0, arg1);
203 return -1;
204#else /* !HAVE_WIN32_PROC */
205 char *devname; 204 char *devname;
206 int ptm; 205 int ptm;
207 pid_t pid; 206 pid_t pid;
@@ -244,7 +243,6 @@ static int create_subprocess(const char *cmd, const char *arg0, const char *arg1
244 cmd, strerror(errno), errno); 243 cmd, strerror(errno), errno);
245 exit(-1); 244 exit(-1);
246 } else { 245 } else {
247#if !ADB_HOST
248 // set child's OOM adjustment to zero 246 // set child's OOM adjustment to zero
249 char text[64]; 247 char text[64];
250 snprintf(text, sizeof text, "/proc/%d/oom_adj", pid); 248 snprintf(text, sizeof text, "/proc/%d/oom_adj", pid);
@@ -255,11 +253,11 @@ static int create_subprocess(const char *cmd, const char *arg0, const char *arg1
255 } else { 253 } else {
256 D("adb: unable to open %s\n", text); 254 D("adb: unable to open %s\n", text);
257 } 255 }
258#endif 256
259 return ptm; 257 return ptm;
260 } 258 }
261#endif /* !HAVE_WIN32_PROC */
262} 259}
260#endif /* !ADB_HOST */
263 261
264#if ADB_HOST 262#if ADB_HOST
265#define SHELL_COMMAND "/bin/sh" 263#define SHELL_COMMAND "/bin/sh"
@@ -267,6 +265,76 @@ static int create_subprocess(const char *cmd, const char *arg0, const char *arg1
267#define SHELL_COMMAND "/system/bin/sh" 265#define SHELL_COMMAND "/system/bin/sh"
268#endif 266#endif
269 267
268#if !ADB_HOST
269static void shell_service(int s, void *command)
270{
271 char buffer[MAX_PAYLOAD];
272 char buffer2[MAX_PAYLOAD];
273 struct pollfd ufds[2];
274 int fd, ret = 0;
275 unsigned count = 0;
276 char** args = (char **)command;
277 fd = create_subprocess(SHELL_COMMAND, args[0], args[1]);
278
279 while (1) {
280 while (count < sizeof(buffer)) {
281 ufds[0].fd = fd;
282 ufds[0].events = POLLIN | POLLHUP;
283 ufds[0].revents = 0;
284 ufds[1].fd = s;
285 ufds[1].events = POLLIN | POLLHUP;
286 ufds[1].revents = 0;
287 // use a 100ms timeout so we don't block indefinitely with our
288 // buffer partially filled.
289 ret = poll(ufds, 2, 100);
290 if (ret <= 0) {
291 D("poll returned %d\n", ret);
292 // file has closed or we timed out
293 // set ret to 1 so we don't exit the outer loop
294 ret = 1;
295 break;
296 }
297
298 if (ufds[0].revents & POLLIN) {
299 ret = adb_read(fd, buffer + count, sizeof(buffer) - count);
300 D("read fd ret: %d, count: %d\n", ret, count);
301 if (ret > 0)
302 count += ret;
303 else
304 break;
305 }
306 if (ufds[1].revents & POLLIN) {
307 ret = adb_read(s, buffer2, sizeof(buffer2));
308 D("read s ret: %d\n", ret);
309 if (ret > 0)
310 adb_write(fd, buffer2, ret);
311 else
312 break;
313 }
314
315 if ((ufds[0].revents & POLLHUP) || (ufds[1].revents & POLLHUP)) {
316 // set flag to exit after flushing the buffer
317 ret = -1;
318 break;
319 }
320 }
321
322 D("writing: %d\n", count);
323 if (count > 0) {
324 adb_write(s, buffer, count);
325 count = 0;
326 }
327 if (ret <= 0)
328 break;
329 }
330
331 D("shell_service done\n");
332
333 adb_close(fd);
334 adb_close(s);
335}
336#endif // !ADB_HOST
337
270int service_to_fd(const char *name) 338int service_to_fd(const char *name)
271{ 339{
272 int ret = -1; 340 int ret = -1;
@@ -317,14 +385,16 @@ int service_to_fd(const char *name)
317 ret = create_jdwp_connection_fd(atoi(name+5)); 385 ret = create_jdwp_connection_fd(atoi(name+5));
318 } else if (!strncmp(name, "log:", 4)) { 386 } else if (!strncmp(name, "log:", 4)) {
319 ret = create_service_thread(log_service, get_log_file_path(name + 4)); 387 ret = create_service_thread(log_service, get_log_file_path(name + 4));
320#endif
321 } else if(!HOST && !strncmp(name, "shell:", 6)) { 388 } else if(!HOST && !strncmp(name, "shell:", 6)) {
389 const char* args[2];
322 if(name[6]) { 390 if(name[6]) {
323 ret = create_subprocess(SHELL_COMMAND, "-c", name + 6); 391 args[0] = "-c";
392 args[1] = name + 6;
324 } else { 393 } else {
325 ret = create_subprocess(SHELL_COMMAND, "-", 0); 394 args[0] = "-";
395 args[1] = 0;
326 } 396 }
327#if !ADB_HOST 397 ret = create_service_thread(shell_service, (void *)args);
328 } else if(!strncmp(name, "sync:", 5)) { 398 } else if(!strncmp(name, "sync:", 5)) {
329 ret = create_service_thread(file_sync_service, NULL); 399 ret = create_service_thread(file_sync_service, NULL);
330 } else if(!strncmp(name, "remount:", 8)) { 400 } else if(!strncmp(name, "remount:", 8)) {