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 "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
fatal(const char * fn,const char * fmt,...)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)
dump_fde(fdevent * fde,const char * info)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
fdevent_init()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
fdevent_connect(fdevent * fde)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
fdevent_disconnect(fdevent * fde)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
fdevent_update(fdevent * fde,unsigned events)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
fdevent_process()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
fdevent_init(void)253 static void fdevent_init(void)
254 {
255 FD_ZERO(&read_fds);
256 FD_ZERO(&write_fds);
257 FD_ZERO(&error_fds);
258 }
259
fdevent_connect(fdevent * fde)260 static void fdevent_connect(fdevent *fde)
261 {
262 if(fde->fd >= select_n) {
263 select_n = fde->fd + 1;
264 }
265 }
266
fdevent_disconnect(fdevent * fde)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
fdevent_update(fdevent * fde,unsigned events)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 */
fdevent_fd_check(fd_set * fds)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
dump_all_fds(const char * extra_msg)324 static inline void dump_all_fds(const char *extra_msg) {}
325 #else
dump_all_fds(const char * extra_msg)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
fdevent_process()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
fdevent_register(fdevent * fde)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
fdevent_unregister(fdevent * fde)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
fdevent_plist_enqueue(fdevent * node)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
fdevent_plist_remove(fdevent * node)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
fdevent_plist_dequeue(void)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
fdevent_call_fdfunc(fdevent * fde)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
fdevent_subproc_event_func(int fd,unsigned ev,void * userdata)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
fdevent_create(int fd,fd_func func,void * arg)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
fdevent_destroy(fdevent * fde)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
fdevent_install(fdevent * fde,int fd,fd_func func,void * arg)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
fdevent_remove(fdevent * fde)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
fdevent_set(fdevent * fde,unsigned events)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
fdevent_add(fdevent * fde,unsigned events)654 void fdevent_add(fdevent *fde, unsigned events)
655 {
656 fdevent_set(
657 fde, (fde->state & FDE_EVENTMASK) | (events & FDE_EVENTMASK));
658 }
659
fdevent_del(fdevent * fde,unsigned events)660 void fdevent_del(fdevent *fde, unsigned events)
661 {
662 fdevent_set(
663 fde, (fde->state & FDE_EVENTMASK) & (~(events & FDE_EVENTMASK)));
664 }
665
fdevent_subproc_setup()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
fdevent_loop()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