• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #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 
fatal(const char * fn,const char * fmt,...)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
dump_fde(fdevent * fde,const char * info)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 
fdevent_init()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 
fdevent_connect(fdevent * fde)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 
fdevent_disconnect(fdevent * fde)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 
fdevent_update(fdevent * fde,unsigned events)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 
fdevent_process()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 
fdevent_init(void)244 static void fdevent_init(void)
245 {
246     FD_ZERO(&read_fds);
247     FD_ZERO(&write_fds);
248     FD_ZERO(&error_fds);
249 }
250 
fdevent_connect(fdevent * fde)251 static void fdevent_connect(fdevent *fde)
252 {
253     if(fde->fd >= select_n) {
254         select_n = fde->fd + 1;
255     }
256 }
257 
fdevent_disconnect(fdevent * fde)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 
fdevent_update(fdevent * fde,unsigned events)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 */
fdevent_fd_check(fd_set * fds)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
dump_all_fds(const char * extra_msg)315 static inline void dump_all_fds(const char *extra_msg) {}
316 #else
dump_all_fds(const char * extra_msg)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 
fdevent_process()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 
fdevent_register(fdevent * fde)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 
fdevent_unregister(fdevent * fde)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 
fdevent_plist_enqueue(fdevent * node)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 
fdevent_plist_remove(fdevent * node)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 
fdevent_plist_dequeue(void)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 
fdevent_call_fdfunc(fdevent * fde)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 
fdevent_subproc_event_func(int fd,unsigned ev,void * userdata)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 
fdevent_create(int fd,fd_func func,void * arg)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 
fdevent_destroy(fdevent * fde)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 
fdevent_install(fdevent * fde,int fd,fd_func func,void * arg)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 
fdevent_remove(fdevent * fde)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 
fdevent_set(fdevent * fde,unsigned events)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 
fdevent_add(fdevent * fde,unsigned events)645 void fdevent_add(fdevent *fde, unsigned events)
646 {
647     fdevent_set(
648         fde, (fde->state & FDE_EVENTMASK) | (events & FDE_EVENTMASK));
649 }
650 
fdevent_del(fdevent * fde,unsigned events)651 void fdevent_del(fdevent *fde, unsigned events)
652 {
653     fdevent_set(
654         fde, (fde->state & FDE_EVENTMASK) & (~(events & FDE_EVENTMASK)));
655 }
656 
fdevent_subproc_setup()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 
fdevent_loop()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