diff options
author | Dan Albert | 2014-11-25 01:32:33 -0600 |
---|---|---|
committer | Dan Albert | 2014-11-25 12:59:42 -0600 |
commit | a01ce3a229aa5d696a282be13d693c7597cfba2f (patch) | |
tree | d1e876fbdf90bdaf348c8b57e6d4a5a3b30f1586 /minadbd | |
parent | d34b63780eaf80ba71279360dc1e2fdbdc488eec (diff) | |
download | platform-bootable-recovery-a01ce3a229aa5d696a282be13d693c7597cfba2f.tar.gz platform-bootable-recovery-a01ce3a229aa5d696a282be13d693c7597cfba2f.tar.xz platform-bootable-recovery-a01ce3a229aa5d696a282be13d693c7597cfba2f.zip |
Start losing code to libadb.
Bug: 17626262
Change-Id: I8ce7cff2b7789f39f35a4211d7120d072c05a863
Diffstat (limited to 'minadbd')
-rw-r--r-- | minadbd/Android.mk | 3 | ||||
-rw-r--r-- | minadbd/fdevent.c | 695 |
2 files changed, 0 insertions, 698 deletions
diff --git a/minadbd/Android.mk b/minadbd/Android.mk index 04956d87..c0771570 100644 --- a/minadbd/Android.mk +++ b/minadbd/Android.mk | |||
@@ -12,7 +12,6 @@ include $(CLEAR_VARS) | |||
12 | 12 | ||
13 | LOCAL_SRC_FILES := \ | 13 | LOCAL_SRC_FILES := \ |
14 | adb.c \ | 14 | adb.c \ |
15 | fdevent.c \ | ||
16 | fuse_adb_provider.c \ | 15 | fuse_adb_provider.c \ |
17 | transport.c \ | 16 | transport.c \ |
18 | transport_usb.c \ | 17 | transport_usb.c \ |
@@ -27,6 +26,4 @@ LOCAL_C_INCLUDES += bootable/recovery | |||
27 | 26 | ||
28 | LOCAL_MODULE := libminadbd | 27 | LOCAL_MODULE := libminadbd |
29 | 28 | ||
30 | LOCAL_STATIC_LIBRARIES := libfusesideload libcutils libc | ||
31 | |||
32 | include $(BUILD_STATIC_LIBRARY) | 29 | include $(BUILD_STATIC_LIBRARY) |
diff --git a/minadbd/fdevent.c b/minadbd/fdevent.c deleted file mode 100644 index 5c374a71..00000000 --- a/minadbd/fdevent.c +++ /dev/null | |||
@@ -1,695 +0,0 @@ | |||
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 | |||
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) | ||
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 | |||
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 | |||
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 | |||
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 | |||
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 | |||
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 | |||
253 | static void fdevent_init(void) | ||
254 | { | ||
255 | FD_ZERO(&read_fds); | ||
256 | FD_ZERO(&write_fds); | ||
257 | FD_ZERO(&error_fds); | ||
258 | } | ||
259 | |||
260 | static void fdevent_connect(fdevent *fde) | ||
261 | { | ||
262 | if(fde->fd >= select_n) { | ||
263 | select_n = fde->fd + 1; | ||
264 | } | ||
265 | } | ||
266 | |||
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 | |||
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 | */ | ||
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 | ||
324 | static inline void dump_all_fds(const char *extra_msg) {} | ||
325 | #else | ||
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 | |||
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 | |||
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 | |||
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 | |||
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 | |||
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 | |||
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 | |||
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 | |||
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 | |||
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 | |||
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 | |||
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 | |||
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 | |||
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 | |||
654 | void fdevent_add(fdevent *fde, unsigned events) | ||
655 | { | ||
656 | fdevent_set( | ||
657 | fde, (fde->state & FDE_EVENTMASK) | (events & FDE_EVENTMASK)); | ||
658 | } | ||
659 | |||
660 | void fdevent_del(fdevent *fde, unsigned events) | ||
661 | { | ||
662 | fdevent_set( | ||
663 | fde, (fde->state & FDE_EVENTMASK) & (~(events & FDE_EVENTMASK))); | ||
664 | } | ||
665 | |||
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 | |||
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 | } | ||