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