system/corennnnn
Révision | f5ed334364e2c8608c92f7f1f39067e8f893b5e0 (tree) |
---|---|
l'heure | 2016-07-20 18:01:29 |
Auteur | Du, Changbin <changbin.du@inte...> |
Commiter | Chih-Wei Huang |
adb: fdevent: add synchronization logic to avoid crash
The fdevent part didn't implemente any synchronization protection. This
could introduce race condition issues. Espacially when adb is used for
Android stress test, this will be a problem that can cause server side
crash.
Change-Id: I93c311ed62770afc3061ccb8b60a0abd09f7453d
Tracked-On: https://jira01.devtools.intel.com/browse/OAM-12574
Signed-off-by: Du, Changbin <changbin.du@intel.com>
Reviewed-on: https://android.intel.com:443/460313
@@ -44,6 +44,8 @@ | ||
44 | 44 | // of the shell's pseudo-tty master. I.e. force close it. |
45 | 45 | int SHELL_EXIT_NOTIFY_FD = -1; |
46 | 46 | |
47 | +ADB_MUTEX_DEFINE( fdevent_lock ); | |
48 | + | |
47 | 49 | static void fatal(const char *fn, const char *fmt, ...) |
48 | 50 | { |
49 | 51 | va_list ap; |
@@ -210,6 +212,7 @@ static void fdevent_process() | ||
210 | 212 | exit(1); |
211 | 213 | } |
212 | 214 | |
215 | + adb_mutex_lock(&fdevent_lock); | |
213 | 216 | for(i = 0; i < n; i++) { |
214 | 217 | struct epoll_event *ev = events + i; |
215 | 218 | fde = ev->data.ptr; |
@@ -229,6 +232,7 @@ static void fdevent_process() | ||
229 | 232 | fdevent_plist_enqueue(fde); |
230 | 233 | } |
231 | 234 | } |
235 | + adb_mutex_unlock(&fdevent_lock); | |
232 | 236 | } |
233 | 237 | |
234 | 238 | #else /* USE_SELECT */ |
@@ -364,13 +368,17 @@ static void fdevent_process() | ||
364 | 368 | unsigned events; |
365 | 369 | fd_set rfd, wfd, efd; |
366 | 370 | |
371 | + adb_mutex_lock(&fdevent_lock); | |
367 | 372 | memcpy(&rfd, &read_fds, sizeof(fd_set)); |
368 | 373 | memcpy(&wfd, &write_fds, sizeof(fd_set)); |
369 | 374 | memcpy(&efd, &error_fds, sizeof(fd_set)); |
370 | 375 | |
371 | 376 | dump_all_fds("pre select()"); |
377 | + adb_mutex_unlock(&fdevent_lock); | |
372 | 378 | |
373 | 379 | n = select(select_n, &rfd, &wfd, &efd, NULL); |
380 | + | |
381 | + adb_mutex_lock(&fdevent_lock); | |
374 | 382 | int saved_errno = errno; |
375 | 383 | D("select() returned n=%d, errno=%d\n", n, n<0?saved_errno:0); |
376 | 384 |
@@ -378,7 +386,7 @@ static void fdevent_process() | ||
378 | 386 | |
379 | 387 | if(n < 0) { |
380 | 388 | switch(saved_errno) { |
381 | - case EINTR: return; | |
389 | + case EINTR: goto unlock; | |
382 | 390 | case EBADF: |
383 | 391 | // Can't trust the FD sets after an error. |
384 | 392 | FD_ZERO(&wfd); |
@@ -387,7 +395,7 @@ static void fdevent_process() | ||
387 | 395 | break; |
388 | 396 | default: |
389 | 397 | D("Unexpected select() error=%d\n", saved_errno); |
390 | - return; | |
398 | + goto unlock; | |
391 | 399 | } |
392 | 400 | } |
393 | 401 | if(n <= 0) { |
@@ -416,6 +424,8 @@ static void fdevent_process() | ||
416 | 424 | fdevent_plist_enqueue(fde); |
417 | 425 | } |
418 | 426 | } |
427 | +unlock: | |
428 | + adb_mutex_unlock(&fdevent_lock); | |
419 | 429 | } |
420 | 430 | |
421 | 431 | #endif |
@@ -500,14 +510,16 @@ static fdevent *fdevent_plist_dequeue(void) | ||
500 | 510 | return node; |
501 | 511 | } |
502 | 512 | |
503 | -static void fdevent_call_fdfunc(fdevent* fde) | |
513 | +static void fdevent_call_fdfunc_locked(fdevent* fde) | |
504 | 514 | { |
505 | 515 | unsigned events = fde->events; |
506 | 516 | fde->events = 0; |
507 | 517 | if(!(fde->state & FDE_PENDING)) return; |
508 | 518 | fde->state &= (~FDE_PENDING); |
509 | 519 | dump_fde(fde, "callback"); |
520 | + adb_mutex_unlock(&fdevent_lock); | |
510 | 521 | fde->func(fde->fd, events, fde->arg); |
522 | + adb_mutex_lock(&fdevent_lock); | |
511 | 523 | } |
512 | 524 | |
513 | 525 | static void fdevent_subproc_event_func(int fd, unsigned ev, |
@@ -523,6 +535,7 @@ static void fdevent_subproc_event_func(int fd, unsigned ev, | ||
523 | 535 | fdevent *fde = fd_table[fd]; |
524 | 536 | fdevent_add(fde, FDE_READ); |
525 | 537 | |
538 | + adb_mutex_lock(&fdevent_lock); | |
526 | 539 | if(ev & FDE_READ){ |
527 | 540 | int subproc_fd; |
528 | 541 |
@@ -532,17 +545,17 @@ static void fdevent_subproc_event_func(int fd, unsigned ev, | ||
532 | 545 | if((subproc_fd < 0) || (subproc_fd >= fd_table_max)) { |
533 | 546 | D("subproc_fd %d out of range 0, fd_table_max=%d\n", |
534 | 547 | subproc_fd, fd_table_max); |
535 | - return; | |
548 | + goto unlock; | |
536 | 549 | } |
537 | 550 | fdevent *subproc_fde = fd_table[subproc_fd]; |
538 | 551 | if(!subproc_fde) { |
539 | 552 | D("subproc_fd %d cleared from fd_table\n", subproc_fd); |
540 | - return; | |
553 | + goto unlock; | |
541 | 554 | } |
542 | 555 | if(subproc_fde->fd != subproc_fd) { |
543 | 556 | // Already reallocated? |
544 | 557 | D("subproc_fd %d != fd_table[].fd %d\n", subproc_fd, subproc_fde->fd); |
545 | - return; | |
558 | + goto unlock; | |
546 | 559 | } |
547 | 560 | |
548 | 561 | subproc_fde->force_eof = 1; |
@@ -556,17 +569,19 @@ static void fdevent_subproc_event_func(int fd, unsigned ev, | ||
556 | 569 | // If there is data left, it will show up in the select(). |
557 | 570 | // This works because there is no other thread reading that |
558 | 571 | // data when in this fd_func(). |
559 | - return; | |
572 | + goto unlock; | |
560 | 573 | } |
561 | 574 | |
562 | 575 | D("subproc_fde.state=%04x\n", subproc_fde->state); |
563 | 576 | subproc_fde->events |= FDE_READ; |
564 | 577 | if(subproc_fde->state & FDE_PENDING) { |
565 | - return; | |
578 | + goto unlock; | |
566 | 579 | } |
567 | 580 | subproc_fde->state |= FDE_PENDING; |
568 | - fdevent_call_fdfunc(subproc_fde); | |
581 | + fdevent_call_fdfunc_locked(subproc_fde); | |
569 | 582 | } |
583 | +unlock: | |
584 | + adb_mutex_unlock(&fdevent_lock); | |
570 | 585 | } |
571 | 586 | |
572 | 587 | fdevent *fdevent_create(int fd, fd_func func, void *arg) |
@@ -590,6 +605,7 @@ void fdevent_destroy(fdevent *fde) | ||
590 | 605 | |
591 | 606 | void fdevent_install(fdevent *fde, int fd, fd_func func, void *arg) |
592 | 607 | { |
608 | + adb_mutex_lock(&fdevent_lock); | |
593 | 609 | memset(fde, 0, sizeof(fdevent)); |
594 | 610 | fde->state = FDE_ACTIVE; |
595 | 611 | fde->fd = fd; |
@@ -604,10 +620,12 @@ void fdevent_install(fdevent *fde, int fd, fd_func func, void *arg) | ||
604 | 620 | dump_fde(fde, "connect"); |
605 | 621 | fdevent_connect(fde); |
606 | 622 | fde->state |= FDE_ACTIVE; |
623 | + adb_mutex_unlock(&fdevent_lock); | |
607 | 624 | } |
608 | 625 | |
609 | 626 | void fdevent_remove(fdevent *fde) |
610 | 627 | { |
628 | + adb_mutex_lock(&fdevent_lock); | |
611 | 629 | if(fde->state & FDE_PENDING) { |
612 | 630 | fdevent_plist_remove(fde); |
613 | 631 | } |
@@ -620,6 +638,7 @@ void fdevent_remove(fdevent *fde) | ||
620 | 638 | |
621 | 639 | fde->state = 0; |
622 | 640 | fde->events = 0; |
641 | + adb_mutex_unlock(&fdevent_lock); | |
623 | 642 | } |
624 | 643 | |
625 | 644 |
@@ -627,7 +646,11 @@ void fdevent_set(fdevent *fde, unsigned events) | ||
627 | 646 | { |
628 | 647 | events &= FDE_EVENTMASK; |
629 | 648 | |
630 | - if((fde->state & FDE_EVENTMASK) == events) return; | |
649 | + adb_mutex_lock(&fdevent_lock); | |
650 | + if((fde->state & FDE_EVENTMASK) == events) { | |
651 | + adb_mutex_unlock(&fdevent_lock); | |
652 | + return; | |
653 | + } | |
631 | 654 | |
632 | 655 | if(fde->state & FDE_ACTIVE) { |
633 | 656 | fdevent_update(fde, events); |
@@ -647,6 +670,7 @@ void fdevent_set(fdevent *fde, unsigned events) | ||
647 | 670 | fde->state &= (~FDE_PENDING); |
648 | 671 | } |
649 | 672 | } |
673 | + adb_mutex_unlock(&fdevent_lock); | |
650 | 674 | } |
651 | 675 | |
652 | 676 | void fdevent_add(fdevent *fde, unsigned events) |
@@ -688,8 +712,10 @@ void fdevent_loop() | ||
688 | 712 | |
689 | 713 | fdevent_process(); |
690 | 714 | |
715 | + adb_mutex_lock(&fdevent_lock); | |
691 | 716 | while((fde = fdevent_plist_dequeue())) { |
692 | - fdevent_call_fdfunc(fde); | |
717 | + fdevent_call_fdfunc_locked(fde); | |
693 | 718 | } |
719 | + adb_mutex_unlock(&fdevent_lock); | |
694 | 720 | } |
695 | 721 | } |
@@ -8,6 +8,7 @@ | ||
8 | 8 | #endif |
9 | 9 | ADB_MUTEX(socket_list_lock) |
10 | 10 | ADB_MUTEX(transport_lock) |
11 | +ADB_MUTEX(fdevent_lock) | |
11 | 12 | #if ADB_HOST |
12 | 13 | ADB_MUTEX(local_transports_lock) |
13 | 14 | #endif |
@@ -27,6 +27,9 @@ | ||
27 | 27 | |
28 | 28 | #include "adb.h" |
29 | 29 | |
30 | +/* TODO: implemente fdevent synchronization for Windows platform. */ | |
31 | +ADB_MUTEX_DEFINE( fdevent_lock ); | |
32 | + | |
30 | 33 | extern void fatal(const char *fmt, ...); |
31 | 34 | |
32 | 35 | /* forward declarations */ |