Changeset 5ebff60 for lib/events_libevent.c
- Timestamp:
- 2015-02-20T22:50:54Z (9 years ago)
- Branches:
- master
- Children:
- 0b9daac, 3d45471, 7733b8c
- Parents:
- af359b4
- git-author:
- Indent <please@…> (19-02-15 05:47:20)
- git-committer:
- dequis <dx@…> (20-02-15 22:50:54)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
lib/events_libevent.c
raf359b4 r5ebff60 1 1 /********************************************************************\ 2 2 * BitlBee -- An IRC to other IM-networks gateway * 3 3 * * … … 53 53 struct event_base *old_leh; 54 54 55 struct b_event_data 56 { 55 struct b_event_data { 57 56 guint id; 58 57 struct event evinfo; … … 65 64 void b_main_init() 66 65 { 67 if( leh != NULL ) 68 { 66 if (leh != NULL) { 69 67 /* Clean up the hash tables? */ 70 68 71 69 b_main_restart(); 72 70 old_leh = leh; 73 71 } 74 72 75 73 leh = event_init(); 76 77 id_hash = g_hash_table_new( g_int_hash, g_int_equal);78 read_hash = g_hash_table_new( g_int_hash, g_int_equal);79 write_hash = g_hash_table_new( g_int_hash, g_int_equal);74 75 id_hash = g_hash_table_new(g_int_hash, g_int_equal); 76 read_hash = g_hash_table_new(g_int_hash, g_int_equal); 77 write_hash = g_hash_table_new(g_int_hash, g_int_equal); 80 78 } 81 79 … … 84 82 /* This while loop is necessary to exit the event loop and start a 85 83 different one (necessary for ForkDaemon mode). */ 86 while( event_base_dispatch( leh ) == 0 && !quitting ) 87 { 88 if( old_leh != NULL ) 89 { 84 while (event_base_dispatch(leh) == 0 && !quitting) { 85 if (old_leh != NULL) { 90 86 /* For some reason this just isn't allowed... 91 87 Possibly a bug in older versions, will see later. … … 93 89 old_leh = NULL; 94 90 } 95 96 event_debug( "New event loop.\n");91 92 event_debug("New event loop.\n"); 97 93 } 98 94 } … … 101 97 { 102 98 struct timeval tv; 103 104 memset( &tv, 0, sizeof( struct timeval ));105 event_base_loopexit( leh, &tv);106 107 event_debug( "b_main_restart()\n");99 100 memset(&tv, 0, sizeof(struct timeval)); 101 event_base_loopexit(leh, &tv); 102 103 event_debug("b_main_restart()\n"); 108 104 } 109 105 … … 114 110 we want to stop them. */ 115 111 quitting = 1; 116 112 117 113 b_main_restart(); 118 114 } 119 115 120 static void b_event_passthrough( int fd, short event, void *data)116 static void b_event_passthrough(int fd, short event, void *data) 121 117 { 122 118 struct b_event_data *b_ev = data; 123 119 b_input_condition cond = 0; 124 120 gboolean st; 125 126 if( fd >= 0 ) 127 { 128 if( event & EV_READ ) 121 122 if (fd >= 0) { 123 if (event & EV_READ) { 129 124 cond |= B_EV_IO_READ; 130 if( event & EV_WRITE ) 125 } 126 if (event & EV_WRITE) { 131 127 cond |= B_EV_IO_WRITE; 132 } 133 134 event_debug( "b_event_passthrough( %d, %d, 0x%x ) (%d)\n", fd, event, (int) data, b_ev->id ); 135 128 } 129 } 130 131 event_debug("b_event_passthrough( %d, %d, 0x%x ) (%d)\n", fd, event, (int) data, b_ev->id); 132 136 133 /* Since the called function might cancel this handler already 137 134 (which free()s b_ev), we have to remember the ID here. */ 138 135 id_cur = b_ev->id; 139 136 id_dead = 0; 140 141 if( quitting ) 142 { 143 b_event_remove( id_cur ); 137 138 if (quitting) { 139 b_event_remove(id_cur); 144 140 return; 145 141 } 146 147 st = b_ev->function( b_ev->data, fd, cond ); 148 if( id_dead ) 149 { 142 143 st = b_ev->function(b_ev->data, fd, cond); 144 if (id_dead) { 150 145 /* This event was killed already, don't touch it! */ 151 146 return; 152 } 153 else if( !st && !( b_ev->flags & B_EV_FLAG_FORCE_REPEAT ) ) 154 { 155 event_debug( "Handler returned FALSE: " ); 156 b_event_remove( id_cur ); 157 } 158 else if( fd == -1 ) 159 { 147 } else if (!st && !(b_ev->flags & B_EV_FLAG_FORCE_REPEAT)) { 148 event_debug("Handler returned FALSE: "); 149 b_event_remove(id_cur); 150 } else if (fd == -1) { 160 151 /* fd == -1 means it was a timer. These can't be auto-repeated 161 152 so it has to be recreated every time. */ 162 153 struct timeval tv; 163 154 164 155 tv.tv_sec = b_ev->timeout / 1000; 165 tv.tv_usec = ( b_ev->timeout % 1000) * 1000;166 167 evtimer_add( &b_ev->evinfo, &tv);168 } 169 } 170 171 gint b_input_add( gint fd, b_input_condition condition, b_event_handler function, gpointer data)156 tv.tv_usec = (b_ev->timeout % 1000) * 1000; 157 158 evtimer_add(&b_ev->evinfo, &tv); 159 } 160 } 161 162 gint b_input_add(gint fd, b_input_condition condition, b_event_handler function, gpointer data) 172 163 { 173 164 struct b_event_data *b_ev; 174 175 event_debug( "b_input_add( %d, %d, 0x%x, 0x%x ) ", fd, condition, function, data ); 176 177 if( ( condition & B_EV_IO_READ && ( b_ev = g_hash_table_lookup( read_hash, &fd ) ) ) || 178 ( condition & B_EV_IO_WRITE && ( b_ev = g_hash_table_lookup( write_hash, &fd ) ) ) ) 179 { 165 166 event_debug("b_input_add( %d, %d, 0x%x, 0x%x ) ", fd, condition, function, data); 167 168 if ((condition & B_EV_IO_READ && (b_ev = g_hash_table_lookup(read_hash, &fd))) || 169 (condition & B_EV_IO_WRITE && (b_ev = g_hash_table_lookup(write_hash, &fd)))) { 180 170 /* We'll stick with this libevent entry, but give it a new BitlBee id. */ 181 g_hash_table_remove( id_hash, &b_ev->id);182 183 event_debug( "(replacing old handler (id = %d)) = %d\n", b_ev->id, id_next);184 171 g_hash_table_remove(id_hash, &b_ev->id); 172 173 event_debug("(replacing old handler (id = %d)) = %d\n", b_ev->id, id_next); 174 185 175 b_ev->id = id_next++; 186 176 b_ev->function = function; 187 177 b_ev->data = data; 188 } 189 else 190 { 178 } else { 191 179 GIOCondition out_cond; 192 193 event_debug( "(new) = %d\n", id_next);194 195 b_ev = g_new0( struct b_event_data, 1);180 181 event_debug("(new) = %d\n", id_next); 182 183 b_ev = g_new0(struct b_event_data, 1); 196 184 b_ev->id = id_next++; 197 185 b_ev->function = function; 198 186 b_ev->data = data; 199 187 200 188 out_cond = EV_PERSIST; 201 if ( condition & B_EV_IO_READ )189 if (condition & B_EV_IO_READ) { 202 190 out_cond |= EV_READ; 203 if( condition & B_EV_IO_WRITE ) 191 } 192 if (condition & B_EV_IO_WRITE) { 204 193 out_cond |= EV_WRITE; 205 206 event_set( &b_ev->evinfo, fd, out_cond, b_event_passthrough, b_ev ); 207 event_add( &b_ev->evinfo, NULL ); 208 209 if( out_cond & EV_READ ) 210 g_hash_table_insert( read_hash, &b_ev->evinfo.ev_fd, b_ev ); 211 if( out_cond & EV_WRITE ) 212 g_hash_table_insert( write_hash, &b_ev->evinfo.ev_fd, b_ev ); 213 } 214 194 } 195 196 event_set(&b_ev->evinfo, fd, out_cond, b_event_passthrough, b_ev); 197 event_add(&b_ev->evinfo, NULL); 198 199 if (out_cond & EV_READ) { 200 g_hash_table_insert(read_hash, &b_ev->evinfo.ev_fd, b_ev); 201 } 202 if (out_cond & EV_WRITE) { 203 g_hash_table_insert(write_hash, &b_ev->evinfo.ev_fd, b_ev); 204 } 205 } 206 215 207 b_ev->flags = condition; 216 g_hash_table_insert( id_hash, &b_ev->id, b_ev);208 g_hash_table_insert(id_hash, &b_ev->id, b_ev); 217 209 return b_ev->id; 218 210 } 219 211 220 212 /* TODO: Persistence for timers! */ 221 gint b_timeout_add( gint timeout, b_event_handler function, gpointer data)222 { 223 struct b_event_data *b_ev = g_new0( struct b_event_data, 1);213 gint b_timeout_add(gint timeout, b_event_handler function, gpointer data) 214 { 215 struct b_event_data *b_ev = g_new0(struct b_event_data, 1); 224 216 struct timeval tv; 225 217 226 218 b_ev->id = id_next++; 227 219 b_ev->timeout = timeout; 228 220 b_ev->function = function; 229 221 b_ev->data = data; 230 222 231 223 tv.tv_sec = timeout / 1000; 232 tv.tv_usec = ( timeout % 1000) * 1000;233 234 evtimer_set( &b_ev->evinfo, b_event_passthrough, b_ev);235 evtimer_add( &b_ev->evinfo, &tv);236 237 event_debug( "b_timeout_add( %d, 0x%x, 0x%x ) = %d\n", timeout, function, data, b_ev->id);238 239 g_hash_table_insert( id_hash, &b_ev->id, b_ev);240 224 tv.tv_usec = (timeout % 1000) * 1000; 225 226 evtimer_set(&b_ev->evinfo, b_event_passthrough, b_ev); 227 evtimer_add(&b_ev->evinfo, &tv); 228 229 event_debug("b_timeout_add( %d, 0x%x, 0x%x ) = %d\n", timeout, function, data, b_ev->id); 230 231 g_hash_table_insert(id_hash, &b_ev->id, b_ev); 232 241 233 return b_ev->id; 242 234 } 243 235 244 void b_event_remove( gint id ) 245 { 246 struct b_event_data *b_ev = g_hash_table_lookup( id_hash, &id ); 247 248 event_debug( "b_event_remove( %d )\n", id ); 249 if( b_ev ) 250 { 251 if( id == id_cur ) 236 void b_event_remove(gint id) 237 { 238 struct b_event_data *b_ev = g_hash_table_lookup(id_hash, &id); 239 240 event_debug("b_event_remove( %d )\n", id); 241 if (b_ev) { 242 if (id == id_cur) { 252 243 id_dead = TRUE; 253 254 g_hash_table_remove( id_hash, &b_ev->id ); 255 if( b_ev->evinfo.ev_fd >= 0 )256 {257 if ( b_ev->evinfo.ev_events & EV_READ )258 g_hash_table_remove( read_hash, &b_ev->evinfo.ev_fd);259 if( b_ev->evinfo.ev_events & EV_WRITE )260 g_hash_table_remove( write_hash, &b_ev->evinfo.ev_fd );261 }262 263 event_del( &b_ev->evinfo );264 g_free( b_ev ); 265 }266 else267 {268 event_debug( "Already removed?\n");269 } 270 } 271 272 void closesocket( int fd)244 } 245 246 g_hash_table_remove(id_hash, &b_ev->id); 247 if (b_ev->evinfo.ev_fd >= 0) { 248 if (b_ev->evinfo.ev_events & EV_READ) { 249 g_hash_table_remove(read_hash, &b_ev->evinfo.ev_fd); 250 } 251 if (b_ev->evinfo.ev_events & EV_WRITE) { 252 g_hash_table_remove(write_hash, &b_ev->evinfo.ev_fd); 253 } 254 } 255 256 event_del(&b_ev->evinfo); 257 g_free(b_ev); 258 } else { 259 event_debug("Already removed?\n"); 260 } 261 } 262 263 void closesocket(int fd) 273 264 { 274 265 struct b_event_data *b_ev; 275 266 276 267 /* Since epoll() (the main reason we use libevent) automatically removes sockets from 277 268 the epoll() list when a socket gets closed and some modules have a habit of … … 279 270 get a little bit messed up. So this little function will remove the handlers 280 271 properly before closing a socket. */ 281 282 if( ( b_ev = g_hash_table_lookup( read_hash, &fd ) ) ) 283 { 284 event_debug( "Warning: fd %d still had a read event handler when shutting down.\n", fd ); 285 b_event_remove( b_ev->id ); 286 } 287 if( ( b_ev = g_hash_table_lookup( write_hash, &fd ) ) ) 288 { 289 event_debug( "Warning: fd %d still had a write event handler when shutting down.\n", fd ); 290 b_event_remove( b_ev->id ); 291 } 292 293 close( fd ); 294 } 272 273 if ((b_ev = g_hash_table_lookup(read_hash, &fd))) { 274 event_debug("Warning: fd %d still had a read event handler when shutting down.\n", fd); 275 b_event_remove(b_ev->id); 276 } 277 if ((b_ev = g_hash_table_lookup(write_hash, &fd))) { 278 event_debug("Warning: fd %d still had a write event handler when shutting down.\n", fd); 279 b_event_remove(b_ev->id); 280 } 281 282 close(fd); 283 }
Note: See TracChangeset
for help on using the changeset viewer.