blob: 0c43c5e9c76fe41c7fb2d8ba107701053fc80fe8 [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
Dan Albert33134262015-03-19 15:21:08 -070018#define TRACE_TAG TRACE_FDEVENT
JP Abgrall408fa572011-03-16 15:57:42 -070019
Dan Albert33134262015-03-19 15:21:08 -070020#include "sysdeps.h"
21#include "fdevent.h"
22
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080023#include <errno.h>
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080024#include <fcntl.h>
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080025#include <stdarg.h>
26#include <stddef.h>
Dan Albert33134262015-03-19 15:21:08 -070027#include <stdio.h>
28#include <stdlib.h>
29#include <string.h>
30#include <sys/ioctl.h>
31#include <unistd.h>
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080032
Dan Albertcc731cc2015-02-24 21:26:58 -080033#include "adb_io.h"
leozwangd3fc15f2014-07-29 12:50:02 -070034#include "adb_trace.h"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080035
JP Abgrall408fa572011-03-16 15:57:42 -070036/* !!! 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;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080046
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{
JP Abgrall408fa572011-03-16 15:57:42 -070062 adb_mutex_lock(&D_lock);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080063 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);
JP Abgrall408fa572011-03-16 15:57:42 -070068 adb_mutex_unlock(&D_lock);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080069}
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);
JP Abgrall408fa572011-03-16 15:57:42 -070084static void fdevent_subproc_event_func(int fd, unsigned events, void *userdata);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080085
86static fdevent list_pending = {
87 .next = &list_pending,
88 .prev = &list_pending,
Dan Albert630b9af2014-11-24 23:34:35 -080089 .fd = -1,
90 .force_eof = 0,
91 .state = 0,
92 .events = 0,
93 .func = nullptr,
94 .arg = nullptr,
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080095};
96
97static fdevent **fd_table = 0;
98static int fd_table_max = 0;
99
Dan Albert45741ae2014-09-25 15:10:34 -0700100#ifdef CRAPTASTIC
101//HAVE_EPOLL
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800102
103#include <sys/epoll.h>
104
105static int epoll_fd = -1;
106
107static void fdevent_init()
108{
Dan Albert45741ae2014-09-25 15:10:34 -0700109 /* XXX: what's a good size for the passed in hint? */
110 epoll_fd = epoll_create(256);
111
112 if(epoll_fd < 0) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800113 perror("epoll_create() failed");
114 exit(1);
115 }
Dan Albert45741ae2014-09-25 15:10:34 -0700116
117 /* mark for close-on-exec */
118 fcntl(epoll_fd, F_SETFD, FD_CLOEXEC);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800119}
120
121static void fdevent_connect(fdevent *fde)
122{
Dan Albert45741ae2014-09-25 15:10:34 -0700123 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
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800135}
136
137static void fdevent_disconnect(fdevent *fde)
138{
139 struct epoll_event ev;
David 'Digit' Turnerf6330a22009-05-18 17:36:28 +0200140
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800141 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;
David 'Digit' Turnerf6330a22009-05-18 17:36:28 +0200157
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800158 active = (fde->state & FDE_EVENTMASK) != 0;
David 'Digit' Turnerf6330a22009-05-18 17:36:28 +0200159
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800160 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;
David 'Digit' Turnerf6330a22009-05-18 17:36:28 +0200265
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800266 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
JP Abgrall408fa572011-03-16 15:57:42 -0700294 fde->state = (fde->state & FDE_STATEMASK) | events;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800295}
296
JP Abgrall408fa572011-03-16 15:57:42 -0700297/* 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
Dan Albert630b9af2014-11-24 23:34:35 -0800319static inline void dump_all_fds(const char* /* extra_msg */) {}
JP Abgrall408fa572011-03-16 15:57:42 -0700320#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
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800360static 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));
David 'Digit' Turnerf6330a22009-05-18 17:36:28 +0200370
JP Abgrall408fa572011-03-16 15:57:42 -0700371 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()");
David 'Digit' Turnerf6330a22009-05-18 17:36:28 +0200378
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800379 if(n < 0) {
JP Abgrall408fa572011-03-16 15:57:42 -0700380 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);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800397 }
398
399 for(i = 0; (i < select_n) && (n > 0); i++) {
400 events = 0;
JP Abgrall408fa572011-03-16 15:57:42 -0700401 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--; }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800404
405 if(events) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800406 fde = fd_table[i];
JP Abgrall408fa572011-03-16 15:57:42 -0700407 if(fde == 0)
408 FATAL("missing fde for fd %d\n", i);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800409
410 fde->events |= events;
David 'Digit' Turnerf6330a22009-05-18 17:36:28 +0200411
JP Abgrall408fa572011-03-16 15:57:42 -0700412 D("got events fde->fd=%d events=%04x, state=%04x\n",
413 fde->fd, fde->events, fde->state);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800414 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 }
David 'Digit' Turnerf6330a22009-05-18 17:36:28 +0200428
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800429 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 }
Dan Albert630b9af2014-11-24 23:34:35 -0800441 fd_table = reinterpret_cast<fdevent**>(
442 realloc(fd_table, sizeof(fdevent*) * fd_table_max));
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800443 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) {
JP Abgrall408fa572011-03-16 15:57:42 -0700459 FATAL("fd_table out of sync [%d]\n", fde->fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800460 }
461
462 fd_table[fde->fd] = 0;
463
464 if(!(fde->state & FDE_DONT_CLOSE)) {
465 dump_fde(fde, "close");
JP Abgrall408fa572011-03-16 15:57:42 -0700466 adb_close(fde->fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800467 }
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;
David 'Digit' Turnerf6330a22009-05-18 17:36:28 +0200492
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800493 if(node == list) return 0;
David 'Digit' Turnerf6330a22009-05-18 17:36:28 +0200494
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800495 list->next = node->next;
496 list->next->prev = list;
497 node->next = 0;
498 node->prev = 0;
499
500 return node;
501}
502
JP Abgrall408fa572011-03-16 15:57:42 -0700503static 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
Dan Albert630b9af2014-11-24 23:34:35 -0800513static void fdevent_subproc_event_func(int fd, unsigned ev,
514 void* /* userdata */)
JP Abgrall408fa572011-03-16 15:57:42 -0700515{
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
Dan Albertcc731cc2015-02-24 21:26:58 -0800529 if(!ReadFdExactly(fd, &subproc_fd, sizeof(subproc_fd))) {
JP Abgrall408fa572011-03-16 15:57:42 -0700530 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;
JP Abgrallb40367e2011-03-29 12:36:22 -0700551 ioctl(subproc_fd, FIONREAD, &rcount);
JP Abgrall408fa572011-03-16 15:57:42 -0700552 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
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800572fdevent *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);
SungHyun Kwonabb80e02015-03-03 13:56:42 +0900588 free(fde);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800589}
590
JP Abgrall408fa572011-03-16 15:57:42 -0700591void fdevent_install(fdevent *fde, int fd, fd_func func, void *arg)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800592{
593 memset(fde, 0, sizeof(fdevent));
594 fde->state = FDE_ACTIVE;
595 fde->fd = fd;
JP Abgrall408fa572011-03-16 15:57:42 -0700596 fde->force_eof = 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800597 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);
JP Abgrall408fa572011-03-16 15:57:42 -0700617 dump_fde(fde, "disconnect");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800618 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;
David 'Digit' Turnerf6330a22009-05-18 17:36:28 +0200629
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800630 if((fde->state & FDE_EVENTMASK) == events) return;
David 'Digit' Turnerf6330a22009-05-18 17:36:28 +0200631
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800632 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
JP Abgrall408fa572011-03-16 15:57:42 -0700664void fdevent_subproc_setup()
665{
666 int s[2];
667
668 if(adb_socketpair(s)) {
669 FATAL("cannot create shell-exit socket-pair\n");
670 }
leozwangcbf02672014-08-15 09:51:27 -0700671 D("socketpair: (%d,%d)", s[0], s[1]);
672
JP Abgrall408fa572011-03-16 15:57:42 -0700673 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
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800681void fdevent_loop()
682{
683 fdevent *fde;
JP Abgrall408fa572011-03-16 15:57:42 -0700684 fdevent_subproc_setup();
David 'Digit' Turnerf6330a22009-05-18 17:36:28 +0200685
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800686 for(;;) {
JP Abgrall408fa572011-03-16 15:57:42 -0700687 D("--- ---- waiting for events\n");
688
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800689 fdevent_process();
David 'Digit' Turnerf6330a22009-05-18 17:36:28 +0200690
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800691 while((fde = fdevent_plist_dequeue())) {
JP Abgrall408fa572011-03-16 15:57:42 -0700692 fdevent_call_fdfunc(fde);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800693 }
694 }
695}