Home | History | Annotate | Download | only in adb
      1 /* http://frotznet.googlecode.com/svn/trunk/utils/fdevent.c
      2 **
      3 ** Copyright 2006, Brian Swetland <swetland (at) frotz.net>
      4 **
      5 ** Licensed under the Apache License, Version 2.0 (the "License");
      6 ** you may not use this file except in compliance with the License.
      7 ** You may obtain a copy of the License at
      8 **
      9 **     http://www.apache.org/licenses/LICENSE-2.0
     10 **
     11 ** Unless required by applicable law or agreed to in writing, software
     12 ** distributed under the License is distributed on an "AS IS" BASIS,
     13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14 ** See the License for the specific language governing permissions and
     15 ** limitations under the License.
     16 */
     17 
     18 #include <sys/ioctl.h>
     19 
     20 #include <stdlib.h>
     21 #include <stdio.h>
     22 #include <string.h>
     23 #include <unistd.h>
     24 #include <errno.h>
     25 
     26 #include <fcntl.h>
     27 
     28 #include <stdarg.h>
     29 #include <stddef.h>
     30 
     31 #include "adb_trace.h"
     32 #include "fdevent.h"
     33 #include "transport.h"
     34 #include "sysdeps.h"
     35 
     36 #define TRACE_TAG  TRACE_FDEVENT
     37 
     38 /* !!! Do not enable DEBUG for the adb that will run as the server:
     39 ** both stdout and stderr are used to communicate between the client
     40 ** and server. Any extra output will cause failures.
     41 */
     42 #define DEBUG 0   /* non-0 will break adb server */
     43 
     44 // This socket is used when a subproc shell service exists.
     45 // It wakes up the fdevent_loop() and cause the correct handling
     46 // of the shell's pseudo-tty master. I.e. force close it.
     47 int SHELL_EXIT_NOTIFY_FD = -1;
     48 
     49 static void fatal(const char *fn, const char *fmt, ...)
     50 {
     51     va_list ap;
     52     va_start(ap, fmt);
     53     fprintf(stderr, "%s:", fn);
     54     vfprintf(stderr, fmt, ap);
     55     va_end(ap);
     56     abort();
     57 }
     58 
     59 #define FATAL(x...) fatal(__FUNCTION__, x)
     60 
     61 #if DEBUG
     62 static void dump_fde(fdevent *fde, const char *info)
     63 {
     64     adb_mutex_lock(&D_lock);
     65     fprintf(stderr,"FDE #%03d %c%c%c %s\n", fde->fd,
     66             fde->state & FDE_READ ? 'R' : ' ',
     67             fde->state & FDE_WRITE ? 'W' : ' ',
     68             fde->state & FDE_ERROR ? 'E' : ' ',
     69             info);
     70     adb_mutex_unlock(&D_lock);
     71 }
     72 #else
     73 #define dump_fde(fde, info) do { } while(0)
     74 #endif
     75 
     76 #define FDE_EVENTMASK  0x00ff
     77 #define FDE_STATEMASK  0xff00
     78 
     79 #define FDE_ACTIVE     0x0100
     80 #define FDE_PENDING    0x0200
     81 #define FDE_CREATED    0x0400
     82 
     83 static void fdevent_plist_enqueue(fdevent *node);
     84 static void fdevent_plist_remove(fdevent *node);
     85 static fdevent *fdevent_plist_dequeue(void);
     86 static void fdevent_subproc_event_func(int fd, unsigned events, void *userdata);
     87 
     88 static fdevent list_pending = {
     89     .next = &list_pending,
     90     .prev = &list_pending,
     91 };
     92 
     93 static fdevent **fd_table = 0;
     94 static int fd_table_max = 0;
     95 
     96 #ifdef CRAPTASTIC
     97 //HAVE_EPOLL
     98 
     99 #include <sys/epoll.h>
    100 
    101 static int epoll_fd = -1;
    102 
    103 static void fdevent_init()
    104 {
    105         /* XXX: what's a good size for the passed in hint? */
    106     epoll_fd = epoll_create(256);
    107 
    108     if(epoll_fd < 0) {
    109         perror("epoll_create() failed");
    110         exit(1);
    111     }
    112 
    113         /* mark for close-on-exec */
    114     fcntl(epoll_fd, F_SETFD, FD_CLOEXEC);
    115 }
    116 
    117 static void fdevent_connect(fdevent *fde)
    118 {
    119     struct epoll_event ev;
    120 
    121     memset(&ev, 0, sizeof(ev));
    122     ev.events = 0;
    123     ev.data.ptr = fde;
    124 
    125 #if 0
    126     if(epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fde->fd, &ev)) {
    127         perror("epoll_ctl() failed\n");
    128         exit(1);
    129     }
    130 #endif
    131 }
    132 
    133 static void fdevent_disconnect(fdevent *fde)
    134 {
    135     struct epoll_event ev;
    136 
    137     memset(&ev, 0, sizeof(ev));
    138     ev.events = 0;
    139     ev.data.ptr = fde;
    140 
    141         /* technically we only need to delete if we
    142         ** were actively monitoring events, but let's
    143         ** be aggressive and do it anyway, just in case
    144         ** something's out of sync
    145         */
    146     epoll_ctl(epoll_fd, EPOLL_CTL_DEL, fde->fd, &ev);
    147 }
    148 
    149 static void fdevent_update(fdevent *fde, unsigned events)
    150 {
    151     struct epoll_event ev;
    152     int active;
    153 
    154     active = (fde->state & FDE_EVENTMASK) != 0;
    155 
    156     memset(&ev, 0, sizeof(ev));
    157     ev.events = 0;
    158     ev.data.ptr = fde;
    159 
    160     if(events & FDE_READ) ev.events |= EPOLLIN;
    161     if(events & FDE_WRITE) ev.events |= EPOLLOUT;
    162     if(events & FDE_ERROR) ev.events |= (EPOLLERR | EPOLLHUP);
    163 
    164     fde->state = (fde->state & FDE_STATEMASK) | events;
    165 
    166     if(active) {
    167             /* we're already active. if we're changing to *no*
    168             ** events being monitored, we need to delete, otherwise
    169             ** we need to just modify
    170             */
    171         if(ev.events) {
    172             if(epoll_ctl(epoll_fd, EPOLL_CTL_MOD, fde->fd, &ev)) {
    173                 perror("epoll_ctl() failed\n");
    174                 exit(1);
    175             }
    176         } else {
    177             if(epoll_ctl(epoll_fd, EPOLL_CTL_DEL, fde->fd, &ev)) {
    178                 perror("epoll_ctl() failed\n");
    179                 exit(1);
    180             }
    181         }
    182     } else {
    183             /* we're not active.  if we're watching events, we need
    184             ** to add, otherwise we can just do nothing
    185             */
    186         if(ev.events) {
    187             if(epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fde->fd, &ev)) {
    188                 perror("epoll_ctl() failed\n");
    189                 exit(1);
    190             }
    191         }
    192     }
    193 }
    194 
    195 static void fdevent_process()
    196 {
    197     struct epoll_event events[256];
    198     fdevent *fde;
    199     int i, n;
    200 
    201     n = epoll_wait(epoll_fd, events, 256, -1);
    202 
    203     if(n < 0) {
    204         if(errno == EINTR) return;
    205         perror("epoll_wait");
    206         exit(1);
    207     }
    208 
    209     for(i = 0; i < n; i++) {
    210         struct epoll_event *ev = events + i;
    211         fde = ev->data.ptr;
    212 
    213         if(ev->events & EPOLLIN) {
    214             fde->events |= FDE_READ;
    215         }
    216         if(ev->events & EPOLLOUT) {
    217             fde->events |= FDE_WRITE;
    218         }
    219         if(ev->events & (EPOLLERR | EPOLLHUP)) {
    220             fde->events |= FDE_ERROR;
    221         }
    222         if(fde->events) {
    223             if(fde->state & FDE_PENDING) continue;
    224             fde->state |= FDE_PENDING;
    225             fdevent_plist_enqueue(fde);
    226         }
    227     }
    228 }
    229 
    230 #else /* USE_SELECT */
    231 
    232 #ifdef HAVE_WINSOCK
    233 #include <winsock2.h>
    234 #else
    235 #include <sys/select.h>
    236 #endif
    237 
    238 static fd_set read_fds;
    239 static fd_set write_fds;
    240 static fd_set error_fds;
    241 
    242 static int select_n = 0;
    243 
    244 static void fdevent_init(void)
    245 {
    246     FD_ZERO(&read_fds);
    247     FD_ZERO(&write_fds);
    248     FD_ZERO(&error_fds);
    249 }
    250 
    251 static void fdevent_connect(fdevent *fde)
    252 {
    253     if(fde->fd >= select_n) {
    254         select_n = fde->fd + 1;
    255     }
    256 }
    257 
    258 static void fdevent_disconnect(fdevent *fde)
    259 {
    260     int i, n;
    261 
    262     FD_CLR(fde->fd, &read_fds);
    263     FD_CLR(fde->fd, &write_fds);
    264     FD_CLR(fde->fd, &error_fds);
    265 
    266     for(n = 0, i = 0; i < select_n; i++) {
    267         if(fd_table[i] != 0) n = i;
    268     }
    269     select_n = n + 1;
    270 }
    271 
    272 static void fdevent_update(fdevent *fde, unsigned events)
    273 {
    274     if(events & FDE_READ) {
    275         FD_SET(fde->fd, &read_fds);
    276     } else {
    277         FD_CLR(fde->fd, &read_fds);
    278     }
    279     if(events & FDE_WRITE) {
    280         FD_SET(fde->fd, &write_fds);
    281     } else {
    282         FD_CLR(fde->fd, &write_fds);
    283     }
    284     if(events & FDE_ERROR) {
    285         FD_SET(fde->fd, &error_fds);
    286     } else {
    287         FD_CLR(fde->fd, &error_fds);
    288     }
    289 
    290     fde->state = (fde->state & FDE_STATEMASK) | events;
    291 }
    292 
    293 /* Looks at fd_table[] for bad FDs and sets bit in fds.
    294 ** Returns the number of bad FDs.
    295 */
    296 static int fdevent_fd_check(fd_set *fds)
    297 {
    298     int i, n = 0;
    299     fdevent *fde;
    300 
    301     for(i = 0; i < select_n; i++) {
    302         fde = fd_table[i];
    303         if(fde == 0) continue;
    304         if(fcntl(i, F_GETFL, NULL) < 0) {
    305             FD_SET(i, fds);
    306             n++;
    307             // fde->state |= FDE_DONT_CLOSE;
    308 
    309         }
    310     }
    311     return n;
    312 }
    313 
    314 #if !DEBUG
    315 static inline void dump_all_fds(const char *extra_msg) {}
    316 #else
    317 static void dump_all_fds(const char *extra_msg)
    318 {
    319 int i;
    320     fdevent *fde;
    321     // per fd: 4 digits (but really: log10(FD_SETSIZE)), 1 staus, 1 blank
    322     char msg_buff[FD_SETSIZE*6 + 1], *pb=msg_buff;
    323     size_t max_chars = FD_SETSIZE * 6 + 1;
    324     int printed_out;
    325 #define SAFE_SPRINTF(...)                                                    \
    326     do {                                                                     \
    327         printed_out = snprintf(pb, max_chars, __VA_ARGS__);                  \
    328         if (printed_out <= 0) {                                              \
    329             D("... snprintf failed.\n");                                     \
    330             return;                                                          \
    331         }                                                                    \
    332         if (max_chars < (unsigned int)printed_out) {                         \
    333             D("... snprintf out of space.\n");                               \
    334             return;                                                          \
    335         }                                                                    \
    336         pb += printed_out;                                                   \
    337         max_chars -= printed_out;                                            \
    338     } while(0)
    339 
    340     for(i = 0; i < select_n; i++) {
    341         fde = fd_table[i];
    342         SAFE_SPRINTF("%d", i);
    343         if(fde == 0) {
    344             SAFE_SPRINTF("? ");
    345             continue;
    346         }
    347         if(fcntl(i, F_GETFL, NULL) < 0) {
    348             SAFE_SPRINTF("b");
    349         }
    350         SAFE_SPRINTF(" ");
    351     }
    352     D("%s fd_table[]->fd = {%s}\n", extra_msg, msg_buff);
    353 }
    354 #endif
    355 
    356 static void fdevent_process()
    357 {
    358     int i, n;
    359     fdevent *fde;
    360     unsigned events;
    361     fd_set rfd, wfd, efd;
    362 
    363     memcpy(&rfd, &read_fds, sizeof(fd_set));
    364     memcpy(&wfd, &write_fds, sizeof(fd_set));
    365     memcpy(&efd, &error_fds, sizeof(fd_set));
    366 
    367     dump_all_fds("pre select()");
    368 
    369     n = select(select_n, &rfd, &wfd, &efd, NULL);
    370     int saved_errno = errno;
    371     D("select() returned n=%d, errno=%d\n", n, n<0?saved_errno:0);
    372 
    373     dump_all_fds("post select()");
    374 
    375     if(n < 0) {
    376         switch(saved_errno) {
    377         case EINTR: return;
    378         case EBADF:
    379             // Can't trust the FD sets after an error.
    380             FD_ZERO(&wfd);
    381             FD_ZERO(&efd);
    382             FD_ZERO(&rfd);
    383             break;
    384         default:
    385             D("Unexpected select() error=%d\n", saved_errno);
    386             return;
    387         }
    388     }
    389     if(n <= 0) {
    390         // We fake a read, as the rest of the code assumes
    391         // that errors will be detected at that point.
    392         n = fdevent_fd_check(&rfd);
    393     }
    394 
    395     for(i = 0; (i < select_n) && (n > 0); i++) {
    396         events = 0;
    397         if(FD_ISSET(i, &rfd)) { events |= FDE_READ; n--; }
    398         if(FD_ISSET(i, &wfd)) { events |= FDE_WRITE; n--; }
    399         if(FD_ISSET(i, &efd)) { events |= FDE_ERROR; n--; }
    400 
    401         if(events) {
    402             fde = fd_table[i];
    403             if(fde == 0)
    404               FATAL("missing fde for fd %d\n", i);
    405 
    406             fde->events |= events;
    407 
    408             D("got events fde->fd=%d events=%04x, state=%04x\n",
    409                 fde->fd, fde->events, fde->state);
    410             if(fde->state & FDE_PENDING) continue;
    411             fde->state |= FDE_PENDING;
    412             fdevent_plist_enqueue(fde);
    413         }
    414     }
    415 }
    416 
    417 #endif
    418 
    419 static void fdevent_register(fdevent *fde)
    420 {
    421     if(fde->fd < 0) {
    422         FATAL("bogus negative fd (%d)\n", fde->fd);
    423     }
    424 
    425     if(fde->fd >= fd_table_max) {
    426         int oldmax = fd_table_max;
    427         if(fde->fd > 32000) {
    428             FATAL("bogus huuuuge fd (%d)\n", fde->fd);
    429         }
    430         if(fd_table_max == 0) {
    431             fdevent_init();
    432             fd_table_max = 256;
    433         }
    434         while(fd_table_max <= fde->fd) {
    435             fd_table_max *= 2;
    436         }
    437         fd_table = realloc(fd_table, sizeof(fdevent*) * fd_table_max);
    438         if(fd_table == 0) {
    439             FATAL("could not expand fd_table to %d entries\n", fd_table_max);
    440         }
    441         memset(fd_table + oldmax, 0, sizeof(int) * (fd_table_max - oldmax));
    442     }
    443 
    444     fd_table[fde->fd] = fde;
    445 }
    446 
    447 static void fdevent_unregister(fdevent *fde)
    448 {
    449     if((fde->fd < 0) || (fde->fd >= fd_table_max)) {
    450         FATAL("fd out of range (%d)\n", fde->fd);
    451     }
    452 
    453     if(fd_table[fde->fd] != fde) {
    454         FATAL("fd_table out of sync [%d]\n", fde->fd);
    455     }
    456 
    457     fd_table[fde->fd] = 0;
    458 
    459     if(!(fde->state & FDE_DONT_CLOSE)) {
    460         dump_fde(fde, "close");
    461         adb_close(fde->fd);
    462     }
    463 }
    464 
    465 static void fdevent_plist_enqueue(fdevent *node)
    466 {
    467     fdevent *list = &list_pending;
    468 
    469     node->next = list;
    470     node->prev = list->prev;
    471     node->prev->next = node;
    472     list->prev = node;
    473 }
    474 
    475 static void fdevent_plist_remove(fdevent *node)
    476 {
    477     node->prev->next = node->next;
    478     node->next->prev = node->prev;
    479     node->next = 0;
    480     node->prev = 0;
    481 }
    482 
    483 static fdevent *fdevent_plist_dequeue(void)
    484 {
    485     fdevent *list = &list_pending;
    486     fdevent *node = list->next;
    487 
    488     if(node == list) return 0;
    489 
    490     list->next = node->next;
    491     list->next->prev = list;
    492     node->next = 0;
    493     node->prev = 0;
    494 
    495     return node;
    496 }
    497 
    498 static void fdevent_call_fdfunc(fdevent* fde)
    499 {
    500     unsigned events = fde->events;
    501     fde->events = 0;
    502     if(!(fde->state & FDE_PENDING)) return;
    503     fde->state &= (~FDE_PENDING);
    504     dump_fde(fde, "callback");
    505     fde->func(fde->fd, events, fde->arg);
    506 }
    507 
    508 static void fdevent_subproc_event_func(int fd, unsigned ev, void *userdata)
    509 {
    510 
    511     D("subproc handling on fd=%d ev=%04x\n", fd, ev);
    512 
    513     // Hook oneself back into the fde's suitable for select() on read.
    514     if((fd < 0) || (fd >= fd_table_max)) {
    515         FATAL("fd %d out of range for fd_table \n", fd);
    516     }
    517     fdevent *fde = fd_table[fd];
    518     fdevent_add(fde, FDE_READ);
    519 
    520     if(ev & FDE_READ){
    521       int subproc_fd;
    522 
    523       if(readx(fd, &subproc_fd, sizeof(subproc_fd))) {
    524           FATAL("Failed to read the subproc's fd from fd=%d\n", fd);
    525       }
    526       if((subproc_fd < 0) || (subproc_fd >= fd_table_max)) {
    527           D("subproc_fd %d out of range 0, fd_table_max=%d\n",
    528             subproc_fd, fd_table_max);
    529           return;
    530       }
    531       fdevent *subproc_fde = fd_table[subproc_fd];
    532       if(!subproc_fde) {
    533           D("subproc_fd %d cleared from fd_table\n", subproc_fd);
    534           return;
    535       }
    536       if(subproc_fde->fd != subproc_fd) {
    537           // Already reallocated?
    538           D("subproc_fd %d != fd_table[].fd %d\n", subproc_fd, subproc_fde->fd);
    539           return;
    540       }
    541 
    542       subproc_fde->force_eof = 1;
    543 
    544       int rcount = 0;
    545       ioctl(subproc_fd, FIONREAD, &rcount);
    546       D("subproc with fd=%d  has rcount=%d err=%d\n",
    547         subproc_fd, rcount, errno);
    548 
    549       if(rcount) {
    550         // If there is data left, it will show up in the select().
    551         // This works because there is no other thread reading that
    552         // data when in this fd_func().
    553         return;
    554       }
    555 
    556       D("subproc_fde.state=%04x\n", subproc_fde->state);
    557       subproc_fde->events |= FDE_READ;
    558       if(subproc_fde->state & FDE_PENDING) {
    559         return;
    560       }
    561       subproc_fde->state |= FDE_PENDING;
    562       fdevent_call_fdfunc(subproc_fde);
    563     }
    564 }
    565 
    566 fdevent *fdevent_create(int fd, fd_func func, void *arg)
    567 {
    568     fdevent *fde = (fdevent*) malloc(sizeof(fdevent));
    569     if(fde == 0) return 0;
    570     fdevent_install(fde, fd, func, arg);
    571     fde->state |= FDE_CREATED;
    572     return fde;
    573 }
    574 
    575 void fdevent_destroy(fdevent *fde)
    576 {
    577     if(fde == 0) return;
    578     if(!(fde->state & FDE_CREATED)) {
    579         FATAL("fde %p not created by fdevent_create()\n", fde);
    580     }
    581     fdevent_remove(fde);
    582 }
    583 
    584 void fdevent_install(fdevent *fde, int fd, fd_func func, void *arg)
    585 {
    586     memset(fde, 0, sizeof(fdevent));
    587     fde->state = FDE_ACTIVE;
    588     fde->fd = fd;
    589     fde->force_eof = 0;
    590     fde->func = func;
    591     fde->arg = arg;
    592 
    593 #ifndef HAVE_WINSOCK
    594     fcntl(fd, F_SETFL, O_NONBLOCK);
    595 #endif
    596     fdevent_register(fde);
    597     dump_fde(fde, "connect");
    598     fdevent_connect(fde);
    599     fde->state |= FDE_ACTIVE;
    600 }
    601 
    602 void fdevent_remove(fdevent *fde)
    603 {
    604     if(fde->state & FDE_PENDING) {
    605         fdevent_plist_remove(fde);
    606     }
    607 
    608     if(fde->state & FDE_ACTIVE) {
    609         fdevent_disconnect(fde);
    610         dump_fde(fde, "disconnect");
    611         fdevent_unregister(fde);
    612     }
    613 
    614     fde->state = 0;
    615     fde->events = 0;
    616 }
    617 
    618 
    619 void fdevent_set(fdevent *fde, unsigned events)
    620 {
    621     events &= FDE_EVENTMASK;
    622 
    623     if((fde->state & FDE_EVENTMASK) == events) return;
    624 
    625     if(fde->state & FDE_ACTIVE) {
    626         fdevent_update(fde, events);
    627         dump_fde(fde, "update");
    628     }
    629 
    630     fde->state = (fde->state & FDE_STATEMASK) | events;
    631 
    632     if(fde->state & FDE_PENDING) {
    633             /* if we're pending, make sure
    634             ** we don't signal an event that
    635             ** is no longer wanted.
    636             */
    637         fde->events &= (~events);
    638         if(fde->events == 0) {
    639             fdevent_plist_remove(fde);
    640             fde->state &= (~FDE_PENDING);
    641         }
    642     }
    643 }
    644 
    645 void fdevent_add(fdevent *fde, unsigned events)
    646 {
    647     fdevent_set(
    648         fde, (fde->state & FDE_EVENTMASK) | (events & FDE_EVENTMASK));
    649 }
    650 
    651 void fdevent_del(fdevent *fde, unsigned events)
    652 {
    653     fdevent_set(
    654         fde, (fde->state & FDE_EVENTMASK) & (~(events & FDE_EVENTMASK)));
    655 }
    656 
    657 void fdevent_subproc_setup()
    658 {
    659     int s[2];
    660 
    661     if(adb_socketpair(s)) {
    662         FATAL("cannot create shell-exit socket-pair\n");
    663     }
    664     SHELL_EXIT_NOTIFY_FD = s[0];
    665     fdevent *fde;
    666     fde = fdevent_create(s[1], fdevent_subproc_event_func, NULL);
    667     if(!fde)
    668       FATAL("cannot create fdevent for shell-exit handler\n");
    669     fdevent_add(fde, FDE_READ);
    670 }
    671 
    672 void fdevent_loop()
    673 {
    674     fdevent *fde;
    675     fdevent_subproc_setup();
    676 
    677     for(;;) {
    678         D("--- ---- waiting for events\n");
    679 
    680         fdevent_process();
    681 
    682         while((fde = fdevent_plist_dequeue())) {
    683             fdevent_call_fdfunc(fde);
    684         }
    685     }
    686 }
    687