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