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