1dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/* http://frotznet.googlecode.com/svn/trunk/utils/fdevent.c 2dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project** 3dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project** Copyright 2006, Brian Swetland <swetland@frotz.net> 4dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project** 50e7c4274c687446dbe30a814278d7a6b99da8c4eJP Abgrall** Licensed under the Apache License, Version 2.0 (the "License"); 60e7c4274c687446dbe30a814278d7a6b99da8c4eJP Abgrall** you may not use this file except in compliance with the License. 70e7c4274c687446dbe30a814278d7a6b99da8c4eJP Abgrall** You may obtain a copy of the License at 8dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project** 90e7c4274c687446dbe30a814278d7a6b99da8c4eJP Abgrall** http://www.apache.org/licenses/LICENSE-2.0 10dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project** 110e7c4274c687446dbe30a814278d7a6b99da8c4eJP Abgrall** Unless required by applicable law or agreed to in writing, software 120e7c4274c687446dbe30a814278d7a6b99da8c4eJP Abgrall** distributed under the License is distributed on an "AS IS" BASIS, 130e7c4274c687446dbe30a814278d7a6b99da8c4eJP Abgrall** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 140e7c4274c687446dbe30a814278d7a6b99da8c4eJP Abgrall** See the License for the specific language governing permissions and 15dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project** limitations under the License. 16dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project*/ 17dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 18408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall#include <sys/ioctl.h> 19408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall 20dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <stdlib.h> 21dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <stdio.h> 22dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <string.h> 23dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <unistd.h> 24dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <errno.h> 25dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 26dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <fcntl.h> 27dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 28dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <stdarg.h> 29dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <stddef.h> 30dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 31414ff7d98ac8d7610a26206335954ad15f43f3acDavid 'Digit' Turner#include "fdevent.h" 32408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall#include "transport.h" 33408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall#include "sysdeps.h" 34408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall 35dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 36408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall/* !!! Do not enable DEBUG for the adb that will run as the server: 37408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall** both stdout and stderr are used to communicate between the client 38408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall** and server. Any extra output will cause failures. 39408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall*/ 40408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall#define DEBUG 0 /* non-0 will break adb server */ 41dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 42408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall// This socket is used when a subproc shell service exists. 43408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall// It wakes up the fdevent_loop() and cause the correct handling 44408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall// of the shell's pseudo-tty master. I.e. force close it. 45408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrallint SHELL_EXIT_NOTIFY_FD = -1; 46dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 47dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void fatal(const char *fn, const char *fmt, ...) 48dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 49dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project va_list ap; 50dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project va_start(ap, fmt); 51dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fprintf(stderr, "%s:", fn); 52dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project vfprintf(stderr, fmt, ap); 53dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project va_end(ap); 54dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project abort(); 55dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 56dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 57dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define FATAL(x...) fatal(__FUNCTION__, x) 58dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 59dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#if DEBUG 60408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall#define D(...) \ 61408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall do { \ 62408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall adb_mutex_lock(&D_lock); \ 63408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall int save_errno = errno; \ 64408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall fprintf(stderr, "%s::%s():", __FILE__, __FUNCTION__); \ 65408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall errno = save_errno; \ 66408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall fprintf(stderr, __VA_ARGS__); \ 67408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall adb_mutex_unlock(&D_lock); \ 68408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall errno = save_errno; \ 69408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall } while(0) 70dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void dump_fde(fdevent *fde, const char *info) 71dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 72408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall adb_mutex_lock(&D_lock); 73dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fprintf(stderr,"FDE #%03d %c%c%c %s\n", fde->fd, 74dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fde->state & FDE_READ ? 'R' : ' ', 75dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fde->state & FDE_WRITE ? 'W' : ' ', 76dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fde->state & FDE_ERROR ? 'E' : ' ', 77dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project info); 78408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall adb_mutex_unlock(&D_lock); 79dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 80dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#else 81408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall#define D(...) ((void)0) 82dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define dump_fde(fde, info) do { } while(0) 83dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif 84dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 85dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define FDE_EVENTMASK 0x00ff 86dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define FDE_STATEMASK 0xff00 87dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 88dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define FDE_ACTIVE 0x0100 89dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define FDE_PENDING 0x0200 90dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define FDE_CREATED 0x0400 91dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 92dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void fdevent_plist_enqueue(fdevent *node); 93dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void fdevent_plist_remove(fdevent *node); 94dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic fdevent *fdevent_plist_dequeue(void); 95408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrallstatic void fdevent_subproc_event_func(int fd, unsigned events, void *userdata); 96dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 97dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic fdevent list_pending = { 98dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project .next = &list_pending, 99dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project .prev = &list_pending, 100dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}; 101dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 102dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic fdevent **fd_table = 0; 103dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic int fd_table_max = 0; 104dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 105dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#ifdef CRAPTASTIC 106dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project//HAVE_EPOLL 107dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 108dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <sys/epoll.h> 109dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 110dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic int epoll_fd = -1; 111dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 112dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void fdevent_init() 113dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 114dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project /* XXX: what's a good size for the passed in hint? */ 115dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project epoll_fd = epoll_create(256); 116f6330a2eeb78c0971f33feee7fd1ee06472a7dbaDavid 'Digit' Turner 117dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(epoll_fd < 0) { 118dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project perror("epoll_create() failed"); 119dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project exit(1); 120dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 121dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 122dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project /* mark for close-on-exec */ 123dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fcntl(epoll_fd, F_SETFD, FD_CLOEXEC); 124dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 125dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 126dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void fdevent_connect(fdevent *fde) 127dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 128dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct epoll_event ev; 129dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 130dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project memset(&ev, 0, sizeof(ev)); 131dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ev.events = 0; 132dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ev.data.ptr = fde; 133dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 134f6330a2eeb78c0971f33feee7fd1ee06472a7dbaDavid 'Digit' Turner#if 0 135dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fde->fd, &ev)) { 136dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project perror("epoll_ctl() failed\n"); 137dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project exit(1); 138dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 139dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif 140dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 141dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 142dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void fdevent_disconnect(fdevent *fde) 143dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 144dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct epoll_event ev; 145f6330a2eeb78c0971f33feee7fd1ee06472a7dbaDavid 'Digit' Turner 146dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project memset(&ev, 0, sizeof(ev)); 147dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ev.events = 0; 148dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ev.data.ptr = fde; 149dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 150dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project /* technically we only need to delete if we 151dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ** were actively monitoring events, but let's 152dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ** be aggressive and do it anyway, just in case 153dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ** something's out of sync 154dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */ 155dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project epoll_ctl(epoll_fd, EPOLL_CTL_DEL, fde->fd, &ev); 156dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 157dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 158dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void fdevent_update(fdevent *fde, unsigned events) 159dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 160dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct epoll_event ev; 161dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int active; 162f6330a2eeb78c0971f33feee7fd1ee06472a7dbaDavid 'Digit' Turner 163dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project active = (fde->state & FDE_EVENTMASK) != 0; 164f6330a2eeb78c0971f33feee7fd1ee06472a7dbaDavid 'Digit' Turner 165dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project memset(&ev, 0, sizeof(ev)); 166dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ev.events = 0; 167dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ev.data.ptr = fde; 168dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 169dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(events & FDE_READ) ev.events |= EPOLLIN; 170dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(events & FDE_WRITE) ev.events |= EPOLLOUT; 171dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(events & FDE_ERROR) ev.events |= (EPOLLERR | EPOLLHUP); 172dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 173dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fde->state = (fde->state & FDE_STATEMASK) | events; 174dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 175dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(active) { 176dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project /* we're already active. if we're changing to *no* 177dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ** events being monitored, we need to delete, otherwise 178dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ** we need to just modify 179dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */ 180dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(ev.events) { 181dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(epoll_ctl(epoll_fd, EPOLL_CTL_MOD, fde->fd, &ev)) { 182dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project perror("epoll_ctl() failed\n"); 183dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project exit(1); 184dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 185dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } else { 186dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(epoll_ctl(epoll_fd, EPOLL_CTL_DEL, fde->fd, &ev)) { 187dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project perror("epoll_ctl() failed\n"); 188dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project exit(1); 189dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 190dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 191dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } else { 192dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project /* we're not active. if we're watching events, we need 193dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ** to add, otherwise we can just do nothing 194dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */ 195dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(ev.events) { 196dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fde->fd, &ev)) { 197dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project perror("epoll_ctl() failed\n"); 198dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project exit(1); 199dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 200dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 201dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 202dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 203dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 204dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void fdevent_process() 205dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 206dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct epoll_event events[256]; 207dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fdevent *fde; 208dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int i, n; 209dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 210dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project n = epoll_wait(epoll_fd, events, 256, -1); 211dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 212dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(n < 0) { 213dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(errno == EINTR) return; 214dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project perror("epoll_wait"); 215dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project exit(1); 216dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 217dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 218dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project for(i = 0; i < n; i++) { 219dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct epoll_event *ev = events + i; 220dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fde = ev->data.ptr; 221dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 222dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(ev->events & EPOLLIN) { 223dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fde->events |= FDE_READ; 224dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 225dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(ev->events & EPOLLOUT) { 226dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fde->events |= FDE_WRITE; 227dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 228dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(ev->events & (EPOLLERR | EPOLLHUP)) { 229dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fde->events |= FDE_ERROR; 230dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 231dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(fde->events) { 232dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(fde->state & FDE_PENDING) continue; 233dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fde->state |= FDE_PENDING; 234dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fdevent_plist_enqueue(fde); 235dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 236dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 237dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 238dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 239dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#else /* USE_SELECT */ 240dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 241dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#ifdef HAVE_WINSOCK 242dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <winsock2.h> 243dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#else 244dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <sys/select.h> 245dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif 246dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 247dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic fd_set read_fds; 248dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic fd_set write_fds; 249dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic fd_set error_fds; 250dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 251dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic int select_n = 0; 252dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 253dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void fdevent_init(void) 254dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 255dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project FD_ZERO(&read_fds); 256dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project FD_ZERO(&write_fds); 257dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project FD_ZERO(&error_fds); 258dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 259dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 260dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void fdevent_connect(fdevent *fde) 261dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 262dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(fde->fd >= select_n) { 263dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project select_n = fde->fd + 1; 264dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 265dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 266dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 267dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void fdevent_disconnect(fdevent *fde) 268dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 269dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int i, n; 270f6330a2eeb78c0971f33feee7fd1ee06472a7dbaDavid 'Digit' Turner 271dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project FD_CLR(fde->fd, &read_fds); 272dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project FD_CLR(fde->fd, &write_fds); 273dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project FD_CLR(fde->fd, &error_fds); 274dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 275dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project for(n = 0, i = 0; i < select_n; i++) { 276dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(fd_table[i] != 0) n = i; 277dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 278dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project select_n = n + 1; 279dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 280dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 281dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void fdevent_update(fdevent *fde, unsigned events) 282dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 283dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(events & FDE_READ) { 284dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project FD_SET(fde->fd, &read_fds); 285dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } else { 286dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project FD_CLR(fde->fd, &read_fds); 287dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 288dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(events & FDE_WRITE) { 289dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project FD_SET(fde->fd, &write_fds); 290dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } else { 291dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project FD_CLR(fde->fd, &write_fds); 292dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 293dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(events & FDE_ERROR) { 294dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project FD_SET(fde->fd, &error_fds); 295dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } else { 296dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project FD_CLR(fde->fd, &error_fds); 297dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 298dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 299408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall fde->state = (fde->state & FDE_STATEMASK) | events; 300408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall} 301408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall 302408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall/* Looks at fd_table[] for bad FDs and sets bit in fds. 303408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall** Returns the number of bad FDs. 304408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall*/ 305408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrallstatic int fdevent_fd_check(fd_set *fds) 306408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall{ 307408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall int i, n = 0; 308408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall fdevent *fde; 309408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall 310408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall for(i = 0; i < select_n; i++) { 311408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall fde = fd_table[i]; 312408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall if(fde == 0) continue; 313408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall if(fcntl(i, F_GETFL, NULL) < 0) { 314408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall FD_SET(i, fds); 315408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall n++; 316408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall // fde->state |= FDE_DONT_CLOSE; 317408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall 318408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall } 319408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall } 320408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall return n; 321dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 322dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 323408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall#if !DEBUG 324408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrallstatic inline void dump_all_fds(const char *extra_msg) {} 325408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall#else 326408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrallstatic void dump_all_fds(const char *extra_msg) 327408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall{ 328408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrallint i; 329408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall fdevent *fde; 330408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall // per fd: 4 digits (but really: log10(FD_SETSIZE)), 1 staus, 1 blank 331408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall char msg_buff[FD_SETSIZE*6 + 1], *pb=msg_buff; 332408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall size_t max_chars = FD_SETSIZE * 6 + 1; 333408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall int printed_out; 334408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall#define SAFE_SPRINTF(...) \ 335408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall do { \ 336408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall printed_out = snprintf(pb, max_chars, __VA_ARGS__); \ 337408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall if (printed_out <= 0) { \ 338408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall D("... snprintf failed.\n"); \ 339408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall return; \ 340408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall } \ 341408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall if (max_chars < (unsigned int)printed_out) { \ 342408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall D("... snprintf out of space.\n"); \ 343408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall return; \ 344408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall } \ 345408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall pb += printed_out; \ 346408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall max_chars -= printed_out; \ 347408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall } while(0) 348408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall 349408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall for(i = 0; i < select_n; i++) { 350408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall fde = fd_table[i]; 351408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall SAFE_SPRINTF("%d", i); 352408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall if(fde == 0) { 353408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall SAFE_SPRINTF("? "); 354408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall continue; 355408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall } 356408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall if(fcntl(i, F_GETFL, NULL) < 0) { 357408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall SAFE_SPRINTF("b"); 358408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall } 359408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall SAFE_SPRINTF(" "); 360408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall } 361408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall D("%s fd_table[]->fd = {%s}\n", extra_msg, msg_buff); 362408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall} 363408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall#endif 364408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall 365dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void fdevent_process() 366dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 367dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int i, n; 368dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fdevent *fde; 369dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project unsigned events; 370dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fd_set rfd, wfd, efd; 371dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 372dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project memcpy(&rfd, &read_fds, sizeof(fd_set)); 373dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project memcpy(&wfd, &write_fds, sizeof(fd_set)); 374dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project memcpy(&efd, &error_fds, sizeof(fd_set)); 375f6330a2eeb78c0971f33feee7fd1ee06472a7dbaDavid 'Digit' Turner 376408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall dump_all_fds("pre select()"); 377408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall 378408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall n = select(select_n, &rfd, &wfd, &efd, NULL); 379408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall int saved_errno = errno; 380408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall D("select() returned n=%d, errno=%d\n", n, n<0?saved_errno:0); 381408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall 382408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall dump_all_fds("post select()"); 383f6330a2eeb78c0971f33feee7fd1ee06472a7dbaDavid 'Digit' Turner 384dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(n < 0) { 385408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall switch(saved_errno) { 386408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall case EINTR: return; 387408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall case EBADF: 388408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall // Can't trust the FD sets after an error. 389408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall FD_ZERO(&wfd); 390408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall FD_ZERO(&efd); 391408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall FD_ZERO(&rfd); 392408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall break; 393408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall default: 394408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall D("Unexpected select() error=%d\n", saved_errno); 395408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall return; 396408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall } 397408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall } 398408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall if(n <= 0) { 399408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall // We fake a read, as the rest of the code assumes 400408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall // that errors will be detected at that point. 401408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall n = fdevent_fd_check(&rfd); 402dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 403dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 404dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project for(i = 0; (i < select_n) && (n > 0); i++) { 405dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project events = 0; 406408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall if(FD_ISSET(i, &rfd)) { events |= FDE_READ; n--; } 407408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall if(FD_ISSET(i, &wfd)) { events |= FDE_WRITE; n--; } 408408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall if(FD_ISSET(i, &efd)) { events |= FDE_ERROR; n--; } 409dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 410dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(events) { 411dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fde = fd_table[i]; 412408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall if(fde == 0) 413408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall FATAL("missing fde for fd %d\n", i); 414dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 415dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fde->events |= events; 416f6330a2eeb78c0971f33feee7fd1ee06472a7dbaDavid 'Digit' Turner 417408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall D("got events fde->fd=%d events=%04x, state=%04x\n", 418408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall fde->fd, fde->events, fde->state); 419dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(fde->state & FDE_PENDING) continue; 420dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fde->state |= FDE_PENDING; 421dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fdevent_plist_enqueue(fde); 422dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 423dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 424dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 425dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 426dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif 427dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 428dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void fdevent_register(fdevent *fde) 429dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 430dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(fde->fd < 0) { 431dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project FATAL("bogus negative fd (%d)\n", fde->fd); 432dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 433f6330a2eeb78c0971f33feee7fd1ee06472a7dbaDavid 'Digit' Turner 434dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(fde->fd >= fd_table_max) { 435dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int oldmax = fd_table_max; 436dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(fde->fd > 32000) { 437dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project FATAL("bogus huuuuge fd (%d)\n", fde->fd); 438dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 439dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(fd_table_max == 0) { 440dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fdevent_init(); 441dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fd_table_max = 256; 442dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 443dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project while(fd_table_max <= fde->fd) { 444dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fd_table_max *= 2; 445dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 446dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fd_table = realloc(fd_table, sizeof(fdevent*) * fd_table_max); 447dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(fd_table == 0) { 448dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project FATAL("could not expand fd_table to %d entries\n", fd_table_max); 449dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 450dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project memset(fd_table + oldmax, 0, sizeof(int) * (fd_table_max - oldmax)); 451dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 452dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 453dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fd_table[fde->fd] = fde; 454dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 455dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 456dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void fdevent_unregister(fdevent *fde) 457dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 458dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if((fde->fd < 0) || (fde->fd >= fd_table_max)) { 459dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project FATAL("fd out of range (%d)\n", fde->fd); 460dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 461dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 462dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(fd_table[fde->fd] != fde) { 463408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall FATAL("fd_table out of sync [%d]\n", fde->fd); 464dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 465dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 466dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fd_table[fde->fd] = 0; 467dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 468dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(!(fde->state & FDE_DONT_CLOSE)) { 469dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project dump_fde(fde, "close"); 470408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall adb_close(fde->fd); 471dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 472dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 473dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 474dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void fdevent_plist_enqueue(fdevent *node) 475dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 476dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fdevent *list = &list_pending; 477dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 478dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project node->next = list; 479dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project node->prev = list->prev; 480dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project node->prev->next = node; 481dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project list->prev = node; 482dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 483dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 484dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void fdevent_plist_remove(fdevent *node) 485dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 486dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project node->prev->next = node->next; 487dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project node->next->prev = node->prev; 488dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project node->next = 0; 489dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project node->prev = 0; 490dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 491dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 492dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic fdevent *fdevent_plist_dequeue(void) 493dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 494dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fdevent *list = &list_pending; 495dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fdevent *node = list->next; 496f6330a2eeb78c0971f33feee7fd1ee06472a7dbaDavid 'Digit' Turner 497dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(node == list) return 0; 498f6330a2eeb78c0971f33feee7fd1ee06472a7dbaDavid 'Digit' Turner 499dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project list->next = node->next; 500dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project list->next->prev = list; 501dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project node->next = 0; 502dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project node->prev = 0; 503dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 504dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return node; 505dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 506dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 507408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrallstatic void fdevent_call_fdfunc(fdevent* fde) 508408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall{ 509408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall unsigned events = fde->events; 510408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall fde->events = 0; 511408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall if(!(fde->state & FDE_PENDING)) return; 512408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall fde->state &= (~FDE_PENDING); 513408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall dump_fde(fde, "callback"); 514408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall fde->func(fde->fd, events, fde->arg); 515408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall} 516408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall 517408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrallstatic void fdevent_subproc_event_func(int fd, unsigned ev, void *userdata) 518408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall{ 519408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall 520408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall D("subproc handling on fd=%d ev=%04x\n", fd, ev); 521408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall 522408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall // Hook oneself back into the fde's suitable for select() on read. 523408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall if((fd < 0) || (fd >= fd_table_max)) { 524408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall FATAL("fd %d out of range for fd_table \n", fd); 525408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall } 526408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall fdevent *fde = fd_table[fd]; 527408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall fdevent_add(fde, FDE_READ); 528408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall 529408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall if(ev & FDE_READ){ 530408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall int subproc_fd; 531408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall 532408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall if(readx(fd, &subproc_fd, sizeof(subproc_fd))) { 533408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall FATAL("Failed to read the subproc's fd from fd=%d\n", fd); 534408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall } 535408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall if((subproc_fd < 0) || (subproc_fd >= fd_table_max)) { 536408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall D("subproc_fd %d out of range 0, fd_table_max=%d\n", 537408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall subproc_fd, fd_table_max); 538408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall return; 539408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall } 540408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall fdevent *subproc_fde = fd_table[subproc_fd]; 541408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall if(!subproc_fde) { 542408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall D("subproc_fd %d cleared from fd_table\n", subproc_fd); 543408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall return; 544408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall } 545408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall if(subproc_fde->fd != subproc_fd) { 546408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall // Already reallocated? 547408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall D("subproc_fd %d != fd_table[].fd %d\n", subproc_fd, subproc_fde->fd); 548408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall return; 549408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall } 550408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall 551408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall subproc_fde->force_eof = 1; 552408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall 553408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall int rcount = 0; 554b40367e7bc3f89c3875d50b29fa98c3a541e33a3JP Abgrall ioctl(subproc_fd, FIONREAD, &rcount); 555408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall D("subproc with fd=%d has rcount=%d err=%d\n", 556408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall subproc_fd, rcount, errno); 557408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall 558408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall if(rcount) { 559408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall // If there is data left, it will show up in the select(). 560408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall // This works because there is no other thread reading that 561408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall // data when in this fd_func(). 562408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall return; 563408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall } 564408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall 565408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall D("subproc_fde.state=%04x\n", subproc_fde->state); 566408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall subproc_fde->events |= FDE_READ; 567408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall if(subproc_fde->state & FDE_PENDING) { 568408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall return; 569408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall } 570408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall subproc_fde->state |= FDE_PENDING; 571408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall fdevent_call_fdfunc(subproc_fde); 572408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall } 573408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall} 574408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall 575dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectfdevent *fdevent_create(int fd, fd_func func, void *arg) 576dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 577dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fdevent *fde = (fdevent*) malloc(sizeof(fdevent)); 578dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(fde == 0) return 0; 579dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fdevent_install(fde, fd, func, arg); 580dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fde->state |= FDE_CREATED; 581dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return fde; 582dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 583dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 584dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid fdevent_destroy(fdevent *fde) 585dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 586dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(fde == 0) return; 587dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(!(fde->state & FDE_CREATED)) { 588dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project FATAL("fde %p not created by fdevent_create()\n", fde); 589dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 590dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fdevent_remove(fde); 591dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 592dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 593408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrallvoid fdevent_install(fdevent *fde, int fd, fd_func func, void *arg) 594dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 595dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project memset(fde, 0, sizeof(fdevent)); 596dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fde->state = FDE_ACTIVE; 597dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fde->fd = fd; 598408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall fde->force_eof = 0; 599dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fde->func = func; 600dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fde->arg = arg; 601dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 602dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#ifndef HAVE_WINSOCK 603dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fcntl(fd, F_SETFL, O_NONBLOCK); 604dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif 605dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fdevent_register(fde); 606dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project dump_fde(fde, "connect"); 607dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fdevent_connect(fde); 608dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fde->state |= FDE_ACTIVE; 609dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 610dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 611dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid fdevent_remove(fdevent *fde) 612dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 613dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(fde->state & FDE_PENDING) { 614dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fdevent_plist_remove(fde); 615dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 616dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 617dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(fde->state & FDE_ACTIVE) { 618dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fdevent_disconnect(fde); 619408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall dump_fde(fde, "disconnect"); 620dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fdevent_unregister(fde); 621dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 622dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 623dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fde->state = 0; 624dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fde->events = 0; 625dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 626dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 627dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 628dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid fdevent_set(fdevent *fde, unsigned events) 629dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 630dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project events &= FDE_EVENTMASK; 631f6330a2eeb78c0971f33feee7fd1ee06472a7dbaDavid 'Digit' Turner 632dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if((fde->state & FDE_EVENTMASK) == events) return; 633f6330a2eeb78c0971f33feee7fd1ee06472a7dbaDavid 'Digit' Turner 634dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(fde->state & FDE_ACTIVE) { 635dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fdevent_update(fde, events); 636dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project dump_fde(fde, "update"); 637dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 638dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 639dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fde->state = (fde->state & FDE_STATEMASK) | events; 640dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 641dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(fde->state & FDE_PENDING) { 642dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project /* if we're pending, make sure 643dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ** we don't signal an event that 644dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ** is no longer wanted. 645dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */ 646dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fde->events &= (~events); 647dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(fde->events == 0) { 648dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fdevent_plist_remove(fde); 649dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fde->state &= (~FDE_PENDING); 650dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 651dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 652dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 653dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 654dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid fdevent_add(fdevent *fde, unsigned events) 655dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 656dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fdevent_set( 657dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fde, (fde->state & FDE_EVENTMASK) | (events & FDE_EVENTMASK)); 658dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 659dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 660dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid fdevent_del(fdevent *fde, unsigned events) 661dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 662dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fdevent_set( 663dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fde, (fde->state & FDE_EVENTMASK) & (~(events & FDE_EVENTMASK))); 664dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 665dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 666408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrallvoid fdevent_subproc_setup() 667408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall{ 668408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall int s[2]; 669408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall 670408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall if(adb_socketpair(s)) { 671408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall FATAL("cannot create shell-exit socket-pair\n"); 672408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall } 673408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall SHELL_EXIT_NOTIFY_FD = s[0]; 674408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall fdevent *fde; 675408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall fde = fdevent_create(s[1], fdevent_subproc_event_func, NULL); 676408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall if(!fde) 677408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall FATAL("cannot create fdevent for shell-exit handler\n"); 678408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall fdevent_add(fde, FDE_READ); 679408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall} 680408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall 681dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid fdevent_loop() 682dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 683dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fdevent *fde; 684408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall fdevent_subproc_setup(); 685f6330a2eeb78c0971f33feee7fd1ee06472a7dbaDavid 'Digit' Turner 686dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project for(;;) { 687408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall D("--- ---- waiting for events\n"); 688408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall 689dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fdevent_process(); 690f6330a2eeb78c0971f33feee7fd1ee06472a7dbaDavid 'Digit' Turner 691dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project while((fde = fdevent_plist_dequeue())) { 692408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall fdevent_call_fdfunc(fde); 693dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 694dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 695dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 696