blob: 57c9c1592e46bdc903813b79c18425fdbc5767c2 [file] [log] [blame]
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001/* http://frotznet.googlecode.com/svn/trunk/utils/fdevent.c
2**
3** Copyright 2006, Brian Swetland <swetland@frotz.net>
4**
JP Abgrall0e7c4272011-02-23 18:44:39 -08005** 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
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08008**
JP Abgrall0e7c4272011-02-23 18:44:39 -08009** http://www.apache.org/licenses/LICENSE-2.0
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080010**
JP Abgrall0e7c4272011-02-23 18:44:39 -080011** 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
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080015** limitations under the License.
16*/
17
JP Abgrall408fa572011-03-16 15:57:42 -070018#include <sys/ioctl.h>
19
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080020#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
leozwangd3fc15f2014-07-29 12:50:02 -070031#include "adb_trace.h"
David 'Digit' Turner414ff7d2009-05-18 17:07:46 +020032#include "fdevent.h"
JP Abgrall408fa572011-03-16 15:57:42 -070033#include "transport.h"
34#include "sysdeps.h"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080035
leozwangd3fc15f2014-07-29 12:50:02 -070036#define TRACE_TAG TRACE_FDEVENT
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080037
JP Abgrall408fa572011-03-16 15:57:42 -070038/* !!! 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.
47int SHELL_EXIT_NOTIFY_FD = -1;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080048
49static 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
62static void dump_fde(fdevent *fde, const char *info)
63{
JP Abgrall408fa572011-03-16 15:57:42 -070064 adb_mutex_lock(&D_lock);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080065 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);
JP Abgrall408fa572011-03-16 15:57:42 -070070 adb_mutex_unlock(&D_lock);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080071}
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
83static void fdevent_plist_enqueue(fdevent *node);
84static void fdevent_plist_remove(fdevent *node);
85static fdevent *fdevent_plist_dequeue(void);
JP Abgrall408fa572011-03-16 15:57:42 -070086static void fdevent_subproc_event_func(int fd, unsigned events, void *userdata);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080087
88static fdevent list_pending = {
89 .next = &list_pending,
90 .prev = &list_pending,
91};
92
93static fdevent **fd_table = 0;
94static int fd_table_max = 0;
95
Elliott Hughes67de1552014-09-22 11:29:01 -070096#ifdef __linux__
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080097
98#include <sys/epoll.h>
99
100static int epoll_fd = -1;
101
102static void fdevent_init()
103{
Elliott Hughes67de1552014-09-22 11:29:01 -0700104 epoll_fd = epoll_create1(EPOLL_CLOEXEC);
105 if(epoll_fd == -1) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800106 perror("epoll_create() failed");
107 exit(1);
108 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800109}
110
111static void fdevent_connect(fdevent *fde)
112{
Elliott Hughes67de1552014-09-22 11:29:01 -0700113 // Nothing to do here. fdevent_update will handle the EPOLL_CTL_ADD.
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800114}
115
116static void fdevent_disconnect(fdevent *fde)
117{
118 struct epoll_event ev;
David 'Digit' Turnerf6330a22009-05-18 17:36:28 +0200119
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800120 memset(&ev, 0, sizeof(ev));
121 ev.events = 0;
122 ev.data.ptr = fde;
123
124 /* technically we only need to delete if we
125 ** were actively monitoring events, but let's
126 ** be aggressive and do it anyway, just in case
127 ** something's out of sync
128 */
129 epoll_ctl(epoll_fd, EPOLL_CTL_DEL, fde->fd, &ev);
130}
131
132static void fdevent_update(fdevent *fde, unsigned events)
133{
134 struct epoll_event ev;
135 int active;
David 'Digit' Turnerf6330a22009-05-18 17:36:28 +0200136
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800137 active = (fde->state & FDE_EVENTMASK) != 0;
David 'Digit' Turnerf6330a22009-05-18 17:36:28 +0200138
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800139 memset(&ev, 0, sizeof(ev));
140 ev.events = 0;
141 ev.data.ptr = fde;
142
143 if(events & FDE_READ) ev.events |= EPOLLIN;
144 if(events & FDE_WRITE) ev.events |= EPOLLOUT;
145 if(events & FDE_ERROR) ev.events |= (EPOLLERR | EPOLLHUP);
146
147 fde->state = (fde->state & FDE_STATEMASK) | events;
148
149 if(active) {
150 /* we're already active. if we're changing to *no*
151 ** events being monitored, we need to delete, otherwise
152 ** we need to just modify
153 */
154 if(ev.events) {
155 if(epoll_ctl(epoll_fd, EPOLL_CTL_MOD, fde->fd, &ev)) {
156 perror("epoll_ctl() failed\n");
157 exit(1);
158 }
159 } else {
160 if(epoll_ctl(epoll_fd, EPOLL_CTL_DEL, fde->fd, &ev)) {
161 perror("epoll_ctl() failed\n");
162 exit(1);
163 }
164 }
165 } else {
166 /* we're not active. if we're watching events, we need
167 ** to add, otherwise we can just do nothing
168 */
169 if(ev.events) {
170 if(epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fde->fd, &ev)) {
171 perror("epoll_ctl() failed\n");
172 exit(1);
173 }
174 }
175 }
176}
177
178static void fdevent_process()
179{
180 struct epoll_event events[256];
181 fdevent *fde;
182 int i, n;
183
184 n = epoll_wait(epoll_fd, events, 256, -1);
185
186 if(n < 0) {
187 if(errno == EINTR) return;
188 perror("epoll_wait");
189 exit(1);
190 }
191
192 for(i = 0; i < n; i++) {
193 struct epoll_event *ev = events + i;
194 fde = ev->data.ptr;
195
196 if(ev->events & EPOLLIN) {
197 fde->events |= FDE_READ;
198 }
199 if(ev->events & EPOLLOUT) {
200 fde->events |= FDE_WRITE;
201 }
202 if(ev->events & (EPOLLERR | EPOLLHUP)) {
203 fde->events |= FDE_ERROR;
204 }
205 if(fde->events) {
206 if(fde->state & FDE_PENDING) continue;
207 fde->state |= FDE_PENDING;
208 fdevent_plist_enqueue(fde);
209 }
210 }
211}
212
213#else /* USE_SELECT */
214
215#ifdef HAVE_WINSOCK
216#include <winsock2.h>
217#else
218#include <sys/select.h>
219#endif
220
221static fd_set read_fds;
222static fd_set write_fds;
223static fd_set error_fds;
224
225static int select_n = 0;
226
227static void fdevent_init(void)
228{
229 FD_ZERO(&read_fds);
230 FD_ZERO(&write_fds);
231 FD_ZERO(&error_fds);
232}
233
234static void fdevent_connect(fdevent *fde)
235{
236 if(fde->fd >= select_n) {
237 select_n = fde->fd + 1;
238 }
239}
240
241static void fdevent_disconnect(fdevent *fde)
242{
243 int i, n;
David 'Digit' Turnerf6330a22009-05-18 17:36:28 +0200244
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800245 FD_CLR(fde->fd, &read_fds);
246 FD_CLR(fde->fd, &write_fds);
247 FD_CLR(fde->fd, &error_fds);
248
249 for(n = 0, i = 0; i < select_n; i++) {
250 if(fd_table[i] != 0) n = i;
251 }
252 select_n = n + 1;
253}
254
255static void fdevent_update(fdevent *fde, unsigned events)
256{
257 if(events & FDE_READ) {
258 FD_SET(fde->fd, &read_fds);
259 } else {
260 FD_CLR(fde->fd, &read_fds);
261 }
262 if(events & FDE_WRITE) {
263 FD_SET(fde->fd, &write_fds);
264 } else {
265 FD_CLR(fde->fd, &write_fds);
266 }
267 if(events & FDE_ERROR) {
268 FD_SET(fde->fd, &error_fds);
269 } else {
270 FD_CLR(fde->fd, &error_fds);
271 }
272
JP Abgrall408fa572011-03-16 15:57:42 -0700273 fde->state = (fde->state & FDE_STATEMASK) | events;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800274}
275
JP Abgrall408fa572011-03-16 15:57:42 -0700276/* Looks at fd_table[] for bad FDs and sets bit in fds.
277** Returns the number of bad FDs.
278*/
279static int fdevent_fd_check(fd_set *fds)
280{
281 int i, n = 0;
282 fdevent *fde;
283
284 for(i = 0; i < select_n; i++) {
285 fde = fd_table[i];
286 if(fde == 0) continue;
287 if(fcntl(i, F_GETFL, NULL) < 0) {
288 FD_SET(i, fds);
289 n++;
290 // fde->state |= FDE_DONT_CLOSE;
291
292 }
293 }
294 return n;
295}
296
297#if !DEBUG
298static inline void dump_all_fds(const char *extra_msg) {}
299#else
300static void dump_all_fds(const char *extra_msg)
301{
302int i;
303 fdevent *fde;
304 // per fd: 4 digits (but really: log10(FD_SETSIZE)), 1 staus, 1 blank
305 char msg_buff[FD_SETSIZE*6 + 1], *pb=msg_buff;
306 size_t max_chars = FD_SETSIZE * 6 + 1;
307 int printed_out;
308#define SAFE_SPRINTF(...) \
309 do { \
310 printed_out = snprintf(pb, max_chars, __VA_ARGS__); \
311 if (printed_out <= 0) { \
312 D("... snprintf failed.\n"); \
313 return; \
314 } \
315 if (max_chars < (unsigned int)printed_out) { \
316 D("... snprintf out of space.\n"); \
317 return; \
318 } \
319 pb += printed_out; \
320 max_chars -= printed_out; \
321 } while(0)
322
323 for(i = 0; i < select_n; i++) {
324 fde = fd_table[i];
325 SAFE_SPRINTF("%d", i);
326 if(fde == 0) {
327 SAFE_SPRINTF("? ");
328 continue;
329 }
330 if(fcntl(i, F_GETFL, NULL) < 0) {
331 SAFE_SPRINTF("b");
332 }
333 SAFE_SPRINTF(" ");
334 }
335 D("%s fd_table[]->fd = {%s}\n", extra_msg, msg_buff);
336}
337#endif
338
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800339static void fdevent_process()
340{
341 int i, n;
342 fdevent *fde;
343 unsigned events;
344 fd_set rfd, wfd, efd;
345
346 memcpy(&rfd, &read_fds, sizeof(fd_set));
347 memcpy(&wfd, &write_fds, sizeof(fd_set));
348 memcpy(&efd, &error_fds, sizeof(fd_set));
David 'Digit' Turnerf6330a22009-05-18 17:36:28 +0200349
JP Abgrall408fa572011-03-16 15:57:42 -0700350 dump_all_fds("pre select()");
351
352 n = select(select_n, &rfd, &wfd, &efd, NULL);
353 int saved_errno = errno;
354 D("select() returned n=%d, errno=%d\n", n, n<0?saved_errno:0);
355
356 dump_all_fds("post select()");
David 'Digit' Turnerf6330a22009-05-18 17:36:28 +0200357
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800358 if(n < 0) {
JP Abgrall408fa572011-03-16 15:57:42 -0700359 switch(saved_errno) {
360 case EINTR: return;
361 case EBADF:
362 // Can't trust the FD sets after an error.
363 FD_ZERO(&wfd);
364 FD_ZERO(&efd);
365 FD_ZERO(&rfd);
366 break;
367 default:
368 D("Unexpected select() error=%d\n", saved_errno);
369 return;
370 }
371 }
372 if(n <= 0) {
373 // We fake a read, as the rest of the code assumes
374 // that errors will be detected at that point.
375 n = fdevent_fd_check(&rfd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800376 }
377
378 for(i = 0; (i < select_n) && (n > 0); i++) {
379 events = 0;
JP Abgrall408fa572011-03-16 15:57:42 -0700380 if(FD_ISSET(i, &rfd)) { events |= FDE_READ; n--; }
381 if(FD_ISSET(i, &wfd)) { events |= FDE_WRITE; n--; }
382 if(FD_ISSET(i, &efd)) { events |= FDE_ERROR; n--; }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800383
384 if(events) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800385 fde = fd_table[i];
JP Abgrall408fa572011-03-16 15:57:42 -0700386 if(fde == 0)
387 FATAL("missing fde for fd %d\n", i);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800388
389 fde->events |= events;
David 'Digit' Turnerf6330a22009-05-18 17:36:28 +0200390
JP Abgrall408fa572011-03-16 15:57:42 -0700391 D("got events fde->fd=%d events=%04x, state=%04x\n",
392 fde->fd, fde->events, fde->state);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800393 if(fde->state & FDE_PENDING) continue;
394 fde->state |= FDE_PENDING;
395 fdevent_plist_enqueue(fde);
396 }
397 }
398}
399
400#endif
401
402static void fdevent_register(fdevent *fde)
403{
404 if(fde->fd < 0) {
405 FATAL("bogus negative fd (%d)\n", fde->fd);
406 }
David 'Digit' Turnerf6330a22009-05-18 17:36:28 +0200407
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800408 if(fde->fd >= fd_table_max) {
409 int oldmax = fd_table_max;
410 if(fde->fd > 32000) {
411 FATAL("bogus huuuuge fd (%d)\n", fde->fd);
412 }
413 if(fd_table_max == 0) {
414 fdevent_init();
415 fd_table_max = 256;
416 }
417 while(fd_table_max <= fde->fd) {
418 fd_table_max *= 2;
419 }
420 fd_table = realloc(fd_table, sizeof(fdevent*) * fd_table_max);
421 if(fd_table == 0) {
422 FATAL("could not expand fd_table to %d entries\n", fd_table_max);
423 }
424 memset(fd_table + oldmax, 0, sizeof(int) * (fd_table_max - oldmax));
425 }
426
427 fd_table[fde->fd] = fde;
428}
429
430static void fdevent_unregister(fdevent *fde)
431{
432 if((fde->fd < 0) || (fde->fd >= fd_table_max)) {
433 FATAL("fd out of range (%d)\n", fde->fd);
434 }
435
436 if(fd_table[fde->fd] != fde) {
JP Abgrall408fa572011-03-16 15:57:42 -0700437 FATAL("fd_table out of sync [%d]\n", fde->fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800438 }
439
440 fd_table[fde->fd] = 0;
441
442 if(!(fde->state & FDE_DONT_CLOSE)) {
443 dump_fde(fde, "close");
JP Abgrall408fa572011-03-16 15:57:42 -0700444 adb_close(fde->fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800445 }
446}
447
448static void fdevent_plist_enqueue(fdevent *node)
449{
450 fdevent *list = &list_pending;
451
452 node->next = list;
453 node->prev = list->prev;
454 node->prev->next = node;
455 list->prev = node;
456}
457
458static void fdevent_plist_remove(fdevent *node)
459{
460 node->prev->next = node->next;
461 node->next->prev = node->prev;
462 node->next = 0;
463 node->prev = 0;
464}
465
466static fdevent *fdevent_plist_dequeue(void)
467{
468 fdevent *list = &list_pending;
469 fdevent *node = list->next;
David 'Digit' Turnerf6330a22009-05-18 17:36:28 +0200470
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800471 if(node == list) return 0;
David 'Digit' Turnerf6330a22009-05-18 17:36:28 +0200472
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800473 list->next = node->next;
474 list->next->prev = list;
475 node->next = 0;
476 node->prev = 0;
477
478 return node;
479}
480
JP Abgrall408fa572011-03-16 15:57:42 -0700481static void fdevent_call_fdfunc(fdevent* fde)
482{
483 unsigned events = fde->events;
484 fde->events = 0;
485 if(!(fde->state & FDE_PENDING)) return;
486 fde->state &= (~FDE_PENDING);
487 dump_fde(fde, "callback");
488 fde->func(fde->fd, events, fde->arg);
489}
490
491static void fdevent_subproc_event_func(int fd, unsigned ev, void *userdata)
492{
493
494 D("subproc handling on fd=%d ev=%04x\n", fd, ev);
495
496 // Hook oneself back into the fde's suitable for select() on read.
497 if((fd < 0) || (fd >= fd_table_max)) {
498 FATAL("fd %d out of range for fd_table \n", fd);
499 }
500 fdevent *fde = fd_table[fd];
501 fdevent_add(fde, FDE_READ);
502
503 if(ev & FDE_READ){
504 int subproc_fd;
505
506 if(readx(fd, &subproc_fd, sizeof(subproc_fd))) {
507 FATAL("Failed to read the subproc's fd from fd=%d\n", fd);
508 }
509 if((subproc_fd < 0) || (subproc_fd >= fd_table_max)) {
510 D("subproc_fd %d out of range 0, fd_table_max=%d\n",
511 subproc_fd, fd_table_max);
512 return;
513 }
514 fdevent *subproc_fde = fd_table[subproc_fd];
515 if(!subproc_fde) {
516 D("subproc_fd %d cleared from fd_table\n", subproc_fd);
517 return;
518 }
519 if(subproc_fde->fd != subproc_fd) {
520 // Already reallocated?
521 D("subproc_fd %d != fd_table[].fd %d\n", subproc_fd, subproc_fde->fd);
522 return;
523 }
524
525 subproc_fde->force_eof = 1;
526
527 int rcount = 0;
JP Abgrallb40367e2011-03-29 12:36:22 -0700528 ioctl(subproc_fd, FIONREAD, &rcount);
JP Abgrall408fa572011-03-16 15:57:42 -0700529 D("subproc with fd=%d has rcount=%d err=%d\n",
530 subproc_fd, rcount, errno);
531
532 if(rcount) {
533 // If there is data left, it will show up in the select().
534 // This works because there is no other thread reading that
535 // data when in this fd_func().
536 return;
537 }
538
539 D("subproc_fde.state=%04x\n", subproc_fde->state);
540 subproc_fde->events |= FDE_READ;
541 if(subproc_fde->state & FDE_PENDING) {
542 return;
543 }
544 subproc_fde->state |= FDE_PENDING;
545 fdevent_call_fdfunc(subproc_fde);
546 }
547}
548
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800549fdevent *fdevent_create(int fd, fd_func func, void *arg)
550{
551 fdevent *fde = (fdevent*) malloc(sizeof(fdevent));
552 if(fde == 0) return 0;
553 fdevent_install(fde, fd, func, arg);
554 fde->state |= FDE_CREATED;
555 return fde;
556}
557
558void fdevent_destroy(fdevent *fde)
559{
560 if(fde == 0) return;
561 if(!(fde->state & FDE_CREATED)) {
562 FATAL("fde %p not created by fdevent_create()\n", fde);
563 }
564 fdevent_remove(fde);
565}
566
JP Abgrall408fa572011-03-16 15:57:42 -0700567void fdevent_install(fdevent *fde, int fd, fd_func func, void *arg)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800568{
569 memset(fde, 0, sizeof(fdevent));
570 fde->state = FDE_ACTIVE;
571 fde->fd = fd;
JP Abgrall408fa572011-03-16 15:57:42 -0700572 fde->force_eof = 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800573 fde->func = func;
574 fde->arg = arg;
575
576#ifndef HAVE_WINSOCK
577 fcntl(fd, F_SETFL, O_NONBLOCK);
578#endif
579 fdevent_register(fde);
580 dump_fde(fde, "connect");
581 fdevent_connect(fde);
582 fde->state |= FDE_ACTIVE;
583}
584
585void fdevent_remove(fdevent *fde)
586{
587 if(fde->state & FDE_PENDING) {
588 fdevent_plist_remove(fde);
589 }
590
591 if(fde->state & FDE_ACTIVE) {
592 fdevent_disconnect(fde);
JP Abgrall408fa572011-03-16 15:57:42 -0700593 dump_fde(fde, "disconnect");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800594 fdevent_unregister(fde);
595 }
596
597 fde->state = 0;
598 fde->events = 0;
599}
600
601
602void fdevent_set(fdevent *fde, unsigned events)
603{
604 events &= FDE_EVENTMASK;
David 'Digit' Turnerf6330a22009-05-18 17:36:28 +0200605
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800606 if((fde->state & FDE_EVENTMASK) == events) return;
David 'Digit' Turnerf6330a22009-05-18 17:36:28 +0200607
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800608 if(fde->state & FDE_ACTIVE) {
609 fdevent_update(fde, events);
610 dump_fde(fde, "update");
611 }
612
613 fde->state = (fde->state & FDE_STATEMASK) | events;
614
615 if(fde->state & FDE_PENDING) {
616 /* if we're pending, make sure
617 ** we don't signal an event that
618 ** is no longer wanted.
619 */
620 fde->events &= (~events);
621 if(fde->events == 0) {
622 fdevent_plist_remove(fde);
623 fde->state &= (~FDE_PENDING);
624 }
625 }
626}
627
628void fdevent_add(fdevent *fde, unsigned events)
629{
630 fdevent_set(
631 fde, (fde->state & FDE_EVENTMASK) | (events & FDE_EVENTMASK));
632}
633
634void fdevent_del(fdevent *fde, unsigned events)
635{
636 fdevent_set(
637 fde, (fde->state & FDE_EVENTMASK) & (~(events & FDE_EVENTMASK)));
638}
639
JP Abgrall408fa572011-03-16 15:57:42 -0700640void fdevent_subproc_setup()
641{
642 int s[2];
643
644 if(adb_socketpair(s)) {
645 FATAL("cannot create shell-exit socket-pair\n");
646 }
647 SHELL_EXIT_NOTIFY_FD = s[0];
648 fdevent *fde;
649 fde = fdevent_create(s[1], fdevent_subproc_event_func, NULL);
650 if(!fde)
651 FATAL("cannot create fdevent for shell-exit handler\n");
652 fdevent_add(fde, FDE_READ);
653}
654
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800655void fdevent_loop()
656{
657 fdevent *fde;
JP Abgrall408fa572011-03-16 15:57:42 -0700658 fdevent_subproc_setup();
David 'Digit' Turnerf6330a22009-05-18 17:36:28 +0200659
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800660 for(;;) {
JP Abgrall408fa572011-03-16 15:57:42 -0700661 D("--- ---- waiting for events\n");
662
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800663 fdevent_process();
David 'Digit' Turnerf6330a22009-05-18 17:36:28 +0200664
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800665 while((fde = fdevent_plist_dequeue())) {
JP Abgrall408fa572011-03-16 15:57:42 -0700666 fdevent_call_fdfunc(fde);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800667 }
668 }
669}