Browse code

- io_wait support for write - io_wait: added io_watch_chg(..) - updated tcp code to the io_wait api changes

Andrei Pelinescu-Onciul authored on 29/11/2007 21:01:45
Showing 5 changed files
... ...
@@ -3,26 +3,17 @@
3 3
  * 
4 4
  * Copyright (C) 2005 iptelorg GmbH
5 5
  *
6
- * This file is part of ser, a free SIP server.
6
+ * Permission to use, copy, modify, and distribute this software for any
7
+ * purpose with or without fee is hereby granted, provided that the above
8
+ * copyright notice and this permission notice appear in all copies.
7 9
  *
8
- * ser is free software; you can redistribute it and/or modify
9
- * it under the terms of the GNU General Public License as published by
10
- * the Free Software Foundation; either version 2 of the License, or
11
- * (at your option) any later version
12
- *
13
- * For a license to use the ser software under conditions
14
- * other than those described here, or to purchase support for this
15
- * software, please contact iptel.org by e-mail at the following addresses:
16
- *    info@iptel.org
17
- *
18
- * ser is distributed in the hope that it will be useful,
19
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
20
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21
- * GNU General Public License for more details.
22
- *
23
- * You should have received a copy of the GNU General Public License
24
- * along with this program; if not, write to the Free Software
25
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
10
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
26 17
  */
27 18
 /* 
28 19
  * tcp io wait common stuff used by tcp_main.c & tcp_read.c
... ...
@@ -289,7 +280,8 @@ static void destroy_devpoll(io_wait_h* h)
289 289
 #ifdef HAVE_SELECT
290 290
 static int init_select(io_wait_h* h)
291 291
 {
292
-	FD_ZERO(&h->master_set);
292
+	FD_ZERO(&h->master_rset);
293
+	FD_ZERO(&h->master_wset);
293 294
 	return 0;
294 295
 }
295 296
 #endif
... ...
@@ -3,33 +3,24 @@
3 3
  * 
4 4
  * Copyright (C) 2005 iptelorg GmbH
5 5
  *
6
- * This file is part of ser, a free SIP server.
6
+ * Permission to use, copy, modify, and distribute this software for any
7
+ * purpose with or without fee is hereby granted, provided that the above
8
+ * copyright notice and this permission notice appear in all copies.
7 9
  *
8
- * ser is free software; you can redistribute it and/or modify
9
- * it under the terms of the GNU General Public License as published by
10
- * the Free Software Foundation; either version 2 of the License, or
11
- * (at your option) any later version
12
- *
13
- * For a license to use the ser software under conditions
14
- * other than those described here, or to purchase support for this
15
- * software, please contact iptel.org by e-mail at the following addresses:
16
- *    info@iptel.org
17
- *
18
- * ser is distributed in the hope that it will be useful,
19
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
20
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21
- * GNU General Public License for more details.
22
- *
23
- * You should have received a copy of the GNU General Public License
24
- * along with this program; if not, write to the Free Software
25
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
10
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
26 17
  */
27 18
 /*
28 19
  * tcp io wait common stuff used by tcp_main.c & tcp_read.c
29 20
  * All the functions are inline because of speed reasons and because they are
30 21
  * used only from 2 places.
31 22
  * You also have to define:
32
- *     int handle_io(struct fd_map* fm, int idx) (see below)
23
+ *     int handle_io(struct fd_map* fm, short events, int idx) (see below)
33 24
  *     (this could be trivially replaced by a callback pointer entry attached
34 25
  *      to the io_wait handler if more flexibility rather then performance
35 26
  *      is needed)
... ...
@@ -51,6 +42,7 @@
51 51
  *  2006-05-30  sigio 64 bit workarround enabled for kernels < 2.6.5 (andrei)
52 52
  *  2007-11-22  when handle_io() is called in a loop check & stop if the fd was
53 53
  *               removed inside handle_io() (andrei)
54
+ *  2007-11-29  support for write (POLLOUT); added io_watch_chg() (andrei)
54 55
  */
55 56
 
56 57
 
... ...
@@ -116,12 +108,13 @@ struct fd_map{
116 116
 	int fd;               /* fd no */
117 117
 	fd_type type;         /* "data" type */
118 118
 	void* data;           /* pointer to the corresponding structure */
119
+	short events;         /* events we are interested int */
119 120
 };
120 121
 
121 122
 
122 123
 #ifdef HAVE_KQUEUE
123 124
 #ifndef KQ_CHANGES_ARRAY_SIZE
124
-#define KQ_CHANGES_ARRAY_SIZE 128
125
+#define KQ_CHANGES_ARRAY_SIZE 256
125 126
 
126 127
 #ifdef __OS_netbsd
127 128
 #define KEV_UDATA_CAST (intptr_t)
... ...
@@ -154,7 +147,8 @@ struct io_wait_handler{
154 154
 	int dpoll_fd;
155 155
 #endif
156 156
 #ifdef HAVE_SELECT
157
-	fd_set master_set;
157
+	fd_set master_rset; /* read set */
158
+	fd_set master_wset; /* write set */
158 159
 	int max_fd_select; /* maximum select used fd */
159 160
 #endif
160 161
 	/* common stuff for POLL, SIGIO_RT and SELECT
... ...
@@ -184,10 +178,12 @@ typedef struct io_wait_handler io_wait_h;
184 184
 /* add a fd_map structure to the fd hash */
185 185
 static inline struct fd_map* hash_fd_map(	io_wait_h* h,
186 186
 											int fd,
187
+											short events,
187 188
 											fd_type type,
188 189
 											void* data)
189 190
 {
190 191
 	h->fd_hash[fd].fd=fd;
192
+	h->fd_hash[fd].events=events;
191 193
 	h->fd_hash[fd].type=type;
192 194
 	h->fd_hash[fd].data=data;
193 195
 	return &h->fd_hash[fd];
... ...
@@ -199,8 +195,9 @@ static inline struct fd_map* hash_fd_map(	io_wait_h* h,
199 199
 /* generic handle io routine, this must be defined in the including file
200 200
  * (faster then registering a callback pointer)
201 201
  *
202
- * params:  fm  - pointer to a fd hash entry
203
- *          idx - index in the fd_array (or -1 if not known)
202
+ * params:  fm     - pointer to a fd hash entry
203
+ *          events - combinations of POLLIN, POLLOUT, POLLERR & POLLHUP
204
+ *          idx    - index in the fd_array (or -1 if not known)
204 205
  * return: -1 on error
205 206
  *          0 on EAGAIN or when by some other way it is known that no more 
206 207
  *            io events are queued on the fd (the receive buffer is empty).
... ...
@@ -209,9 +206,9 @@ static inline struct fd_map* hash_fd_map(	io_wait_h* h,
209 209
  *         >0 on successfull read from the fd (when there might be more io
210 210
  *            queued -- the receive buffer might still be non-empty)
211 211
  */
212
-inline static int handle_io(struct fd_map* fm, int idx);
212
+inline static int handle_io(struct fd_map* fm, short events, int idx);
213 213
 #else
214
-int handle_io(struct fd_map* fm, int idx);
214
+int handle_io(struct fd_map* fm, short events, int idx);
215 215
 #endif
216 216
 
217 217
 
... ...
@@ -220,6 +217,10 @@ int handle_io(struct fd_map* fm, int idx);
220 220
 /*
221 221
  * kqueue specific function: register a change
222 222
  * (adds a change to the kevent change array, and if full flushes it first)
223
+ *
224
+ * TODO: check if the event already exists in the change list or if it's
225
+ *       complementary to an event in the list (e.g. EVFILT_WRITE, EV_DELETE
226
+ *       and EVFILT_WRITE, EV_ADD for the same fd).
223 227
  * returns: -1 on error, 0 on success
224 228
  */
225 229
 static inline int kq_ev_change(io_wait_h* h, int fd, int filter, int flag, 
... ...
@@ -254,7 +255,15 @@ again:
254 254
 
255 255
 
256 256
 /* generic io_watch_add function
257
+ * Params:
258
+ *     h      - pointer to initialized io_wait handle
259
+ *     fd     - fd to watch
260
+ *     events - bitmap with the fd events for which the fd should be watched
261
+ *              (combination of POLLIN and POLLOUT)
262
+ *     type   - fd type (non 0 value, returned in the call to handle_io)
263
+ *     data   - pointer/private data returned in the handle_io call
257 264
  * returns 0 on success, -1 on error
265
+ *
258 266
  * WARNING: handle_io() can be called immediately (from io_watch_add()) so
259 267
  *  make sure that any dependent init. (e.g. data stuff) is made before
260 268
  *  calling io_watch_add
... ...
@@ -264,15 +273,16 @@ again:
264 264
  *  switch())*/
265 265
 inline static int io_watch_add(	io_wait_h* h,
266 266
 								int fd,
267
+								short events,
267 268
 								fd_type type,
268 269
 								void* data)
269 270
 {
270 271
 
271 272
 	/* helper macros */
272
-#define fd_array_setup \
273
+#define fd_array_setup(ev) \
273 274
 	do{ \
274 275
 		h->fd_array[h->fd_no].fd=fd; \
275
-		h->fd_array[h->fd_no].events=POLLIN; /* useless for select */ \
276
+		h->fd_array[h->fd_no].events=(ev); /* useless for select */ \
276 277
 		h->fd_array[h->fd_no].revents=0;     /* useless for select */ \
277 278
 	}while(0)
278 279
 	
... ...
@@ -311,12 +321,17 @@ inline static int io_watch_add(	io_wait_h* h,
311 311
 	idx=-1;
312 312
 #endif
313 313
 	e=0;
314
-	if (fd==-1){
314
+	/* sanity checks */
315
+	if (unlikely(fd==-1)){
315 316
 		LOG(L_CRIT, "BUG: io_watch_add: fd is -1!\n");
316 317
 		goto error;
317 318
 	}
319
+	if (unlikely((events&(POLLIN|POLLOUT))==0)){
320
+		LOG(L_CRIT, "BUG: io_watch_add: invalid events: 0x%0x\n", events);
321
+		goto error;
322
+	}
318 323
 	/* check if not too big */
319
-	if (h->fd_no>=h->max_fd_no){
324
+	if (unlikely(h->fd_no>=h->max_fd_no)){
320 325
 		LOG(L_CRIT, "ERROR: io_watch_add: maximum fd number exceeded:"
321 326
 				" %d/%d\n", h->fd_no, h->max_fd_no);
322 327
 		goto error;
... ...
@@ -325,35 +340,38 @@ inline static int io_watch_add(	io_wait_h* h,
325 325
 			h, fd, type, data, h->fd_no);
326 326
 	/*  hash sanity check */
327 327
 	e=get_fd_map(h, fd);
328
-	if (e && (e->type!=0 /*F_NONE*/)){
328
+	if (unlikely(e && (e->type!=0 /*F_NONE*/))){
329 329
 		LOG(L_ERR, "ERROR: io_watch_add: trying to overwrite entry %d"
330 330
 				" in the hash(%d, %d, %p) with (%d, %d, %p)\n",
331 331
 				fd, e->fd, e->type, e->data, fd, type, data);
332 332
 		goto error;
333 333
 	}
334 334
 	
335
-	if ((e=hash_fd_map(h, fd, type, data))==0){
335
+	if (unlikely((e=hash_fd_map(h, fd, events, type, data))==0)){
336 336
 		LOG(L_ERR, "ERROR: io_watch_add: failed to hash the fd %d\n", fd);
337 337
 		goto error;
338 338
 	}
339 339
 	switch(h->poll_method){ /* faster then pointer to functions */
340 340
 		case POLL_POLL:
341
-			fd_array_setup;
341
+			fd_array_setup(events);
342 342
 			set_fd_flags(O_NONBLOCK);
343 343
 			break;
344 344
 #ifdef HAVE_SELECT
345 345
 		case POLL_SELECT:
346
-			fd_array_setup;
347
-			FD_SET(fd, &h->master_set);
346
+			fd_array_setup(events);
347
+			if (likely(events & POLLIN))
348
+				FD_SET(fd, &h->master_rset);
349
+			if (unlikely(events & POLLOUT))
350
+				FD_SET(fd, &h->master_wset);
348 351
 			if (h->max_fd_select<fd) h->max_fd_select=fd;
349 352
 			break;
350 353
 #endif
351 354
 #ifdef HAVE_SIGIO_RT
352 355
 		case POLL_SIGIO_RT:
353
-			fd_array_setup;
356
+			fd_array_setup(events);
354 357
 			/* re-set O_ASYNC might be needed, if not done from 
355 358
 			 * io_watch_del (or if somebody wants to add a fd which has
356
-			 * already O_ASYNC/F_SETSIG set on a dupplicate)
359
+			 * already O_ASYNC/F_SETSIG set on a duplicate)
357 360
 			 */
358 361
 			/* set async & signal */
359 362
 			if (fcntl(fd, F_SETOWN, my_pid())==-1){
... ...
@@ -384,11 +402,12 @@ inline static int io_watch_add(	io_wait_h* h,
384 384
 #endif
385 385
 #ifdef HAVE_EPOLL
386 386
 		case POLL_EPOLL_LT:
387
-			ep_event.events=EPOLLIN;
387
+			ep_event.events=(EPOLLIN & ((int)!(events & POLLIN)-1) ) |
388
+							 (EPOLLOUT & ((int)!(events & POLLOUT)-1) );
388 389
 			ep_event.data.ptr=e;
389 390
 again1:
390 391
 			n=epoll_ctl(h->epfd, EPOLL_CTL_ADD, fd, &ep_event);
391
-			if (n==-1){
392
+			if (unlikely(n==-1)){
392 393
 				if (errno==EAGAIN) goto again1;
393 394
 				LOG(L_ERR, "ERROR: io_watch_add: epoll_ctl failed: %s [%d]\n",
394 395
 					strerror(errno), errno);
... ...
@@ -397,11 +416,13 @@ again1:
397 397
 			break;
398 398
 		case POLL_EPOLL_ET:
399 399
 			set_fd_flags(O_NONBLOCK);
400
-			ep_event.events=EPOLLIN|EPOLLET;
400
+			ep_event.events=(EPOLLIN & ((int)!(events & POLLIN)-1) )  |
401
+							 (EPOLLOUT & ((int)!(events & POLLOUT)-1) ) |
402
+							  EPOLLET;
401 403
 			ep_event.data.ptr=e;
402 404
 again2:
403 405
 			n=epoll_ctl(h->epfd, EPOLL_CTL_ADD, fd, &ep_event);
404
-			if (n==-1){
406
+			if (unlikely(n==-1)){
405 407
 				if (errno==EAGAIN) goto again2;
406 408
 				LOG(L_ERR, "ERROR: io_watch_add: epoll_ctl failed: %s [%d]\n",
407 409
 					strerror(errno), errno);
... ...
@@ -413,14 +434,20 @@ again2:
413 413
 #endif
414 414
 #ifdef HAVE_KQUEUE
415 415
 		case POLL_KQUEUE:
416
-			if (kq_ev_change(h, fd, EVFILT_READ, EV_ADD, e)==-1)
416
+			if (likely( events & POLLINT)){
417
+				if (unlikely(kq_ev_change(h, fd, EVFILT_READ, EV_ADD, e)==-1))
418
+				goto error;
419
+			}
420
+			if (unlikely( events & POLLOUT)){
421
+				if (unlikely(kq_ev_change(h, fd, EVFILT_WRITE, EV_ADD, e)==-1))
417 422
 				goto error;
423
+			}
418 424
 			break;
419 425
 #endif
420 426
 #ifdef HAVE_DEVPOLL
421 427
 		case POLL_DEVPOLL:
422 428
 			pfd.fd=fd;
423
-			pfd.events=POLLIN;
429
+			pfd.events=events;
424 430
 			pfd.revents=0;
425 431
 again_devpoll:
426 432
 			if (write(h->dpoll_fd, &pfd, sizeof(pfd))==-1){
... ...
@@ -445,10 +472,12 @@ again_devpoll:
445 445
 	if (check_io){
446 446
 		/* handle possible pre-existing events */
447 447
 		pf.fd=fd;
448
-		pf.events=POLLIN;
448
+		pf.events=events;
449 449
 check_io_again:
450
-		while(e->type && ((n=poll(&pf, 1, 0))>0) && (handle_io(e, idx)>0));
451
-		if (e->type && (n==-1)){
450
+		while(e->type && ((n=poll(&pf, 1, 0))>0) && 
451
+				(handle_io(e, pf.revents, idx)>0) &&
452
+				(pf.revents & e->events));
453
+		if (unlikely(e->type && (n==-1))){
452 454
 			if (errno==EINTR) goto check_io_again;
453 455
 			LOG(L_ERR, "ERROR: io_watch_add: check_io poll: %s [%d]\n",
454 456
 						strerror(errno), errno);
... ...
@@ -482,18 +511,19 @@ inline static int io_watch_del(io_wait_h* h, int fd, int idx, int flags)
482 482
 	
483 483
 #define fix_fd_array \
484 484
 	do{\
485
-			if (idx==-1){ \
485
+			if (unlikely(idx==-1)){ \
486 486
 				/* fix idx if -1 and needed */ \
487 487
 				for (idx=0; (idx<h->fd_no) && \
488 488
 							(h->fd_array[idx].fd!=fd); idx++); \
489 489
 			} \
490
-			if (idx<h->fd_no){ \
490
+			if (likely(idx<h->fd_no)){ \
491 491
 				memmove(&h->fd_array[idx], &h->fd_array[idx+1], \
492 492
 					(h->fd_no-(idx+1))*sizeof(*(h->fd_array))); \
493 493
 			} \
494 494
 	}while(0)
495 495
 	
496 496
 	struct fd_map* e;
497
+	int events;
497 498
 #ifdef HAVE_EPOLL
498 499
 	int n;
499 500
 	struct epoll_event ep_event;
... ...
@@ -505,7 +535,7 @@ inline static int io_watch_del(io_wait_h* h, int fd, int idx, int flags)
505 505
 	int fd_flags;
506 506
 #endif
507 507
 	
508
-	if ((fd<0) || (fd>=h->max_fd_no)){
508
+	if (unlikely((fd<0) || (fd>=h->max_fd_no))){
509 509
 		LOG(L_CRIT, "BUG: io_watch_del: invalid fd %d, not in [0, %d) \n",
510 510
 						fd, h->fd_no);
511 511
 		goto error;
... ...
@@ -514,18 +544,18 @@ inline static int io_watch_del(io_wait_h* h, int fd, int idx, int flags)
514 514
 			h, fd, idx, flags, h->fd_no);
515 515
 	e=get_fd_map(h, fd);
516 516
 	/* more sanity checks */
517
-	if (e==0){
517
+	if (unlikely(e==0)){
518 518
 		LOG(L_CRIT, "BUG: io_watch_del: no corresponding hash entry for %d\n",
519 519
 					fd);
520 520
 		goto error;
521 521
 	}
522
-	if (e->type==0 /*F_NONE*/){
522
+	if (unlikely(e->type==0 /*F_NONE*/)){
523 523
 		LOG(L_ERR, "ERROR: io_watch_del: trying to delete already erased"
524 524
 				" entry %d in the hash(%d, %d, %p) )\n",
525 525
 				fd, e->fd, e->type, e->data);
526 526
 		goto error;
527 527
 	}
528
-	
528
+	events=e->events;
529 529
 	unhash_fd_map(e);
530 530
 	
531 531
 	switch(h->poll_method){
... ...
@@ -534,11 +564,14 @@ inline static int io_watch_del(io_wait_h* h, int fd, int idx, int flags)
534 534
 			break;
535 535
 #ifdef HAVE_SELECT
536 536
 		case POLL_SELECT:
537
-			fix_fd_array;
538
-			FD_CLR(fd, &h->master_set);
539
-			if (h->max_fd_select && (h->max_fd_select==fd))
537
+			if (likely(events & POLLIN))
538
+				FD_CLR(fd, &h->master_rset);
539
+			if (unlikely(events & POLLOUT))
540
+				FD_CLR(fd, &h->master_wset);
541
+			if (unlikely(h->max_fd_select && (h->max_fd_select==fd)))
540 542
 				/* we don't know the prev. max, so we just decrement it */
541 543
 				h->max_fd_select--; 
544
+			fix_fd_array;
542 545
 			break;
543 546
 #endif
544 547
 #ifdef HAVE_SIGIO_RT
... ...
@@ -553,12 +586,12 @@ inline static int io_watch_del(io_wait_h* h, int fd, int idx, int flags)
553 553
 			/*if (!(flags & IO_FD_CLOSING)){*/
554 554
 				/* reset ASYNC */
555 555
 				fd_flags=fcntl(fd, F_GETFL); 
556
-				if (fd_flags==-1){ 
556
+				if (unlikely(fd_flags==-1)){ 
557 557
 					LOG(L_ERR, "ERROR: io_watch_del: fnctl: GETFL failed:" 
558 558
 							" %s [%d]\n", strerror(errno), errno); 
559 559
 					goto error; 
560 560
 				} 
561
-				if (fcntl(fd, F_SETFL, fd_flags&(~O_ASYNC))==-1){ 
561
+				if (unlikely(fcntl(fd, F_SETFL, fd_flags&(~O_ASYNC))==-1)){ 
562 562
 					LOG(L_ERR, "ERROR: io_watch_del: fnctl: SETFL" 
563 563
 								" failed: %s [%d]\n", strerror(errno), errno); 
564 564
 					goto error; 
... ...
@@ -569,15 +602,17 @@ inline static int io_watch_del(io_wait_h* h, int fd, int idx, int flags)
569 569
 		case POLL_EPOLL_LT:
570 570
 		case POLL_EPOLL_ET:
571 571
 			/* epoll doesn't seem to automatically remove sockets,
572
-			 * if the socket is a dupplicate/moved and the original
572
+			 * if the socket is a duplicate/moved and the original
573 573
 			 * is still open. The fd is removed from the epoll set
574 574
 			 * only when the original (and all the  copies?) is/are 
575 575
 			 * closed. This is probably a bug in epoll. --andrei */
576 576
 #ifdef EPOLL_NO_CLOSE_BUG
577 577
 			if (!(flags & IO_FD_CLOSING)){
578 578
 #endif
579
+again_epoll:
579 580
 				n=epoll_ctl(h->epfd, EPOLL_CTL_DEL, fd, &ep_event);
580
-				if (n==-1){
581
+				if (unlikely(n==-1)){
582
+					if (errno==EAGAIN) goto again_epoll;
581 583
 					LOG(L_ERR, "ERROR: io_watch_del: removing fd from epoll "
582 584
 							"list failed: %s [%d]\n", strerror(errno), errno);
583 585
 					goto error;
... ...
@@ -590,8 +625,21 @@ inline static int io_watch_del(io_wait_h* h, int fd, int idx, int flags)
590 590
 #ifdef HAVE_KQUEUE
591 591
 		case POLL_KQUEUE:
592 592
 			if (!(flags & IO_FD_CLOSING)){
593
-				if (kq_ev_change(h, fd, EVFILT_READ, EV_DELETE, 0)==-1)
594
-					goto error;
593
+				if (likely(events & POLLIN)){
594
+					if (unlikely(kq_ev_change(h, fd, EVFILT_READ,
595
+													EV_DELETE, 0) ==-1)){
596
+						/* try to delete the write filter anyway */
597
+						if (events & POLLOUT){
598
+							kq_ev_change(h, fd, EVFILT_WRITE, EV_DELETE, 0);
599
+						}
600
+						goto error;
601
+					}
602
+				}
603
+				if (unlikely(events & POLLOUT)){
604
+					if (unlikely(kq_ev_change(h, fd, EVFILT_WRITE,
605
+													EV_DELETE, 0) ==-1))
606
+						goto error;
607
+				}
595 608
 			}
596 609
 			break;
597 610
 #endif
... ...
@@ -627,6 +675,180 @@ error:
627 627
 
628 628
 
629 629
 
630
+/* parameters:    h - handler 
631
+ *               fd - file descriptor
632
+ *           events - new events to watch for
633
+ *              idx - index in the fd_array if known, -1 if not
634
+ *                    (if index==-1 fd_array will be searched for the
635
+ *                     corresponding fd* entry -- slower but unavoidable in 
636
+ *                     some cases). index is not used (no fd_array) for epoll,
637
+ *                     /dev/poll and kqueue
638
+ * returns 0 if ok, -1 on error */
639
+inline static int io_watch_chg(io_wait_h* h, int fd, short events, int idx )
640
+{
641
+	
642
+#define fd_array_chg(ev) \
643
+	do{\
644
+			if (unlikely(idx==-1)){ \
645
+				/* fix idx if -1 and needed */ \
646
+				for (idx=0; (idx<h->fd_no) && \
647
+							(h->fd_array[idx].fd!=fd); idx++); \
648
+			} \
649
+			if (likely(idx<h->fd_no)){ \
650
+				h->fd_array[idx].events=(ev); \
651
+			} \
652
+	}while(0)
653
+	
654
+	struct fd_map* e;
655
+	int add_events;
656
+	int del_events;
657
+#ifdef HAVE_EPOLL
658
+	int n;
659
+	struct epoll_event ep_event;
660
+#endif
661
+#ifdef HAVE_DEVPOLL
662
+	struct pollfd pfd;
663
+#endif
664
+	
665
+	if (unlikely((fd<0) || (fd>=h->max_fd_no))){
666
+		LOG(L_CRIT, "BUG: io_watch_chg: invalid fd %d, not in [0, %d) \n",
667
+						fd, h->fd_no);
668
+		goto error;
669
+	}
670
+	if (unlikely((events&(POLLIN|POLLOUT))==0)){
671
+		LOG(L_CRIT, "BUG: io_watch_chg: invalid events: 0x%0x\n", events);
672
+		goto error;
673
+	}
674
+	DBG("DBG: io_watch_chg (%p, %d, 0x%x, 0x%x) fd_no=%d called\n",
675
+			h, fd, events, idx, h->fd_no);
676
+	e=get_fd_map(h, fd);
677
+	/* more sanity checks */
678
+	if (unlikely(e==0)){
679
+		LOG(L_CRIT, "BUG: io_watch_chg: no corresponding hash entry for %d\n",
680
+					fd);
681
+		goto error;
682
+	}
683
+	if (unlikely(e->type==0 /*F_NONE*/)){
684
+		LOG(L_ERR, "ERROR: io_watch_chg: trying to change an already erased"
685
+				" entry %d in the hash(%d, %d, %p) )\n",
686
+				fd, e->fd, e->type, e->data);
687
+		goto error;
688
+	}
689
+	
690
+	add_events=events & ~e->events;
691
+	del_events=e->events & ~events;
692
+	e->events=events;
693
+	switch(h->poll_method){
694
+		case POLL_POLL:
695
+			fd_array_chg(events);
696
+			break;
697
+#ifdef HAVE_SELECT
698
+		case POLL_SELECT:
699
+			fd_array_chg(events);
700
+			if (unlikely(del_events & POLLIN))
701
+				FD_CLR(fd, &h->master_rset);
702
+			else if (unlikely(add_events & POLLIN))
703
+				FD_SET(fd, &h->master_rset);
704
+			if (likely(del_events & POLLOUT))
705
+				FD_CLR(fd, &h->master_wset);
706
+			else if (likely(add_events & POLLOUT))
707
+				FD_SET(fd, &h->master_wset);
708
+			break;
709
+#endif
710
+#ifdef HAVE_SIGIO_RT
711
+		case POLL_SIGIO_RT:
712
+			fd_array_chg(events);
713
+			break;
714
+#endif
715
+#ifdef HAVE_EPOLL
716
+		case POLL_EPOLL_LT:
717
+				ep_event.events=(EPOLLIN & ((int)!(events & POLLIN)-1) ) |
718
+								 (EPOLLOUT & ((int)!(events & POLLOUT)-1) );
719
+				ep_event.data.ptr=e;
720
+again_epoll_lt:
721
+				n=epoll_ctl(h->epfd, EPOLL_CTL_MOD, fd, &ep_event);
722
+				if (unlikely(n==-1)){
723
+					if (errno==EAGAIN) goto again_epoll_lt;
724
+					LOG(L_ERR, "ERROR: io_watch_chg: modifying epoll events"
725
+							" failed: %s [%d]\n", strerror(errno), errno);
726
+					goto error;
727
+				}
728
+			break;
729
+		case POLL_EPOLL_ET:
730
+				ep_event.events=(EPOLLIN & ((int)!(events & POLLIN)-1) ) |
731
+								 (EPOLLOUT & ((int)!(events & POLLOUT)-1) ) |
732
+								 EPOLLET;
733
+				ep_event.data.ptr=e;
734
+again_epoll_et:
735
+				n=epoll_ctl(h->epfd, EPOLL_CTL_MOD, fd, &ep_event);
736
+				if (unlikely(n==-1)){
737
+					if (errno==EAGAIN) goto again_epoll_et;
738
+					LOG(L_ERR, "ERROR: io_watch_chg: modifying epoll events"
739
+							" failed: %s [%d]\n", strerror(errno), errno);
740
+					goto error;
741
+				}
742
+			break;
743
+#endif
744
+#ifdef HAVE_KQUEUE
745
+		case POLL_KQUEUE:
746
+			if (unlikely(del_events & POLLIN)){
747
+				if (unlikely(kq_ev_change(h, fd, EVFILT_READ,
748
+														EV_DELETE, 0) ==-1))
749
+						goto error;
750
+			}else if (unlikely(add_events & POLLIN)){
751
+				if (unlikely(kq_ev_change(h, fd, EVFILT_READ, EV_ADD, e) ==-1))
752
+					goto error;
753
+			}
754
+			if (likely(del_events & POLLOUT)){
755
+				if (unlikely(kq_ev_change(h, fd, EVFILT_WRITE,
756
+														EV_DELETE, 0) ==-1))
757
+						goto error;
758
+			}else if (likely(add_events & POLLOUT)){
759
+				if (unlikely(kq_ev_change(h, fd, EVFILT_WRITE, EV_ADD, e)==-1))
760
+					goto error;
761
+			}
762
+			break;
763
+#endif
764
+#ifdef HAVE_DEVPOLL
765
+		case POLL_DEVPOLL:
766
+				/* for /dev/poll the closed fds _must_ be removed
767
+				   (they are not removed automatically on close()) */
768
+				pfd.fd=fd;
769
+				pfd.events=POLLREMOVE;
770
+				pfd.revents=0;
771
+again_devpoll1:
772
+				if (unlikely(write(h->dpoll_fd, &pfd, sizeof(pfd))==-1)){
773
+					if (errno==EINTR) goto again_devpoll1;
774
+					LOG(L_ERR, "ERROR: io_watch_chg: removing fd from "
775
+								"/dev/poll failed: %s [%d]\n", 
776
+								strerror(errno), errno);
777
+					goto error;
778
+				}
779
+again_devpoll2:
780
+				pfd.events=events;
781
+				pfd.revents=0;
782
+				if (unlikely(write(h->dpoll_fd, &pfd, sizeof(pfd))==-1)){
783
+					if (errno==EINTR) goto again_devpoll2;
784
+					LOG(L_ERR, "ERROR: io_watch_chg: re-adding fd to "
785
+								"/dev/poll failed: %s [%d]\n", 
786
+								strerror(errno), errno);
787
+					goto error;
788
+				}
789
+				break;
790
+#endif
791
+		default:
792
+			LOG(L_CRIT, "BUG: io_watch_chg: no support for poll method "
793
+					" %s (%d)\n", poll_method_str[h->poll_method], 
794
+					h->poll_method);
795
+			goto error;
796
+	}
797
+	h->fd_no--;
798
+	return 0;
799
+error:
800
+	return -1;
801
+#undef fix_fd_array
802
+}
803
+
630 804
 /* io_wait_loop_x style function 
631 805
  * wait for io using poll()
632 806
  * params: h      - io_wait handle
... ...
@@ -650,11 +872,12 @@ again:
650 650
 			}
651 651
 		}
652 652
 		for (r=0; (r<h->fd_no) && n; r++){
653
-			if (h->fd_array[r].revents & (POLLIN|POLLERR|POLLHUP)){
653
+			fm=get_fd_map(h, h->fd_array[r].fd);
654
+			if (h->fd_array[r].revents & (fm->events|POLLERR|POLLHUP)){
654 655
 				n--;
655 656
 				/* sanity checks */
656
-				if ((h->fd_array[r].fd >= h->max_fd_no)||
657
-						(h->fd_array[r].fd < 0)){
657
+				if (unlikely((h->fd_array[r].fd >= h->max_fd_no)||
658
+								(h->fd_array[r].fd < 0))){
658 659
 					LOG(L_CRIT, "BUG: io_wait_loop_poll: bad fd %d "
659 660
 							"(no in the 0 - %d range)\n",
660 661
 							h->fd_array[r].fd, h->max_fd_no);
... ...
@@ -662,8 +885,13 @@ again:
662 662
 					h->fd_array[r].events=0; /* clear the events */
663 663
 					continue;
664 664
 				}
665
-				fm=get_fd_map(h, h->fd_array[r].fd);
666
-				while(fm->type && (handle_io(fm, r) > 0) && repeat);
665
+				/* repeat handle_io if repeat, fd still watched (not deleted
666
+				 *  inside handle_io), handle_io returns that there's still
667
+				 *  IO and the fd is still watched for the triggering event */
668
+				while(fm->type && 
669
+						(handle_io(fm, h->fd_array[r].revents, r) > 0) &&
670
+						repeat &&
671
+						(fm->events & h->fd_array[r].revents) );
667 672
 			}
668 673
 		}
669 674
 error:
... ...
@@ -676,17 +904,20 @@ error:
676 676
 /* wait for io using select */
677 677
 inline static int io_wait_loop_select(io_wait_h* h, int t, int repeat)
678 678
 {
679
-	fd_set sel_set;
679
+	fd_set sel_rset;
680
+	fd_set sel_wset;
680 681
 	int n, ret;
681 682
 	struct timeval timeout;
682 683
 	int r;
683 684
 	struct fd_map* fm;
685
+	int revents;
684 686
 	
685 687
 again:
686
-		sel_set=h->master_set;
688
+		sel_rset=h->master_rset;
689
+		sel_wset=h->master_wset;
687 690
 		timeout.tv_sec=t;
688 691
 		timeout.tv_usec=0;
689
-		ret=n=select(h->max_fd_select+1, &sel_set, 0, 0, &timeout);
692
+		ret=n=select(h->max_fd_select+1, &sel_rset, &sel_wset, 0, &timeout);
690 693
 		if (n<0){
691 694
 			if (errno==EINTR) goto again; /* just a signal */
692 695
 			LOG(L_ERR, "ERROR: io_wait_loop_select: select: %s [%d]\n",
... ...
@@ -696,9 +927,15 @@ again:
696 696
 		}
697 697
 		/* use poll fd array */
698 698
 		for(r=0; (r<h->max_fd_no) && n; r++){
699
-			if (FD_ISSET(h->fd_array[r].fd, &sel_set)){
699
+			revents=0;
700
+			if (likely(FD_ISSET(h->fd_array[r].fd, &sel_rset)))
701
+				revents|=POLLIN;
702
+			if (unlikely(FD_ISSET(h->fd_array[r].fd, &sel_wset)))
703
+				revents|=POLLOUT;
704
+			if (likely(revents)){
700 705
 				fm=get_fd_map(h, h->fd_array[r].fd);
701
-				while(fm->type && (handle_io(fm, r)>0) && repeat);
706
+				while(fm->type && (fm->events & revents) && 
707
+						(handle_io(fm, revents, r)>0) && repeat);
702 708
 				n--;
703 709
 			}
704 710
 		};
... ...
@@ -713,10 +950,11 @@ inline static int io_wait_loop_epoll(io_wait_h* h, int t, int repeat)
713 713
 {
714 714
 	int n, r;
715 715
 	struct fd_map* fm;
716
+	int revents;
716 717
 	
717 718
 again:
718 719
 		n=epoll_wait(h->epfd, h->ep_array, h->fd_no, t*1000);
719
-		if (n==-1){
720
+		if (unlikely(n==-1)){
720 721
 			if (errno==EINTR) goto again; /* signal, ignore it */
721 722
 			else{
722 723
 				LOG(L_ERR, "ERROR:io_wait_loop_epoll: "
... ...
@@ -735,9 +973,14 @@ again:
735 735
 		}
736 736
 #endif
737 737
 		for (r=0; r<n; r++){
738
-			if (h->ep_array[r].events & (EPOLLIN|EPOLLERR|EPOLLHUP)){
738
+			revents= (POLLIN & (!(h->ep_array[r].events & EPOLLIN)-1)) |
739
+					 (POLLOUT & (!(h->ep_array[r].events & EPOLLOUT)-1)) |
740
+					 (POLLERR & (!(h->ep_array[r].events & EPOLLERR)-1)) |
741
+					 (POLLHUP & (!(h->ep_array[r].events & EPOLLHUP)-1));
742
+			if (likely(revents)){
739 743
 				fm=(struct fd_map*)h->ep_array[r].data.ptr;
740
-				while(fm->type && (handle_io(fm,-1)>0) && repeat);
744
+				while(fm->type && (fm->events & revents) && 
745
+						(handle_io(fm, revents, -1)>0) && repeat);
741 746
 			}else{
742 747
 				LOG(L_ERR, "ERROR:io_wait_loop_epoll: unexpected event %x"
743 748
 							" on %d/%d, data=%p\n", h->ep_array[r].events,
... ...
@@ -763,7 +1006,7 @@ inline static int io_wait_loop_kqueue(io_wait_h* h, int t, int repeat)
763 763
 again:
764 764
 		n=kevent(h->kq_fd, h->kq_changes, h->kq_nchanges,  h->kq_array,
765 765
 					h->fd_no, &tspec);
766
-		if (n==-1){
766
+		if (unlikely(n==-1)){
767 767
 			if (errno==EINTR) goto again; /* signal, ignore it */
768 768
 			else{
769 769
 				LOG(L_ERR, "ERROR: io_wait_loop_kqueue: kevent:"
... ...
@@ -778,18 +1021,30 @@ again:
778 778
 					r, n, h->kq_array[r].ident, (long)h->kq_array[r].udata,
779 779
 					h->kq_array[r].flags);
780 780
 #endif
781
-			if (h->kq_array[r].flags & EV_ERROR){
781
+#if 0
782
+			if (unlikely(h->kq_array[r].flags & EV_ERROR)){
782 783
 				/* error in changes: we ignore it, it can be caused by
783 784
 				   trying to remove an already closed fd: race between
784
-				   adding smething to the changes array, close() and
785
+				   adding something to the changes array, close() and
785 786
 				   applying the changes */
786 787
 				LOG(L_INFO, "INFO: io_wait_loop_kqueue: kevent error on "
787 788
 							"fd %d: %s [%ld]\n", h->kq_array[r].ident,
788 789
 							strerror(h->kq_array[r].data),
789 790
 							(long)h->kq_array[r].data);
790
-			}else{ /* READ/EOF */
791
+			}else{ 
792
+#endif
791 793
 				fm=(struct fd_map*)h->kq_array[r].udata;
792
-				while(fm->type && (handle_io(fm, -1)>0) && repeat);
794
+				if (likely(h->kq_array[r].filter==EVFILT_READ)){
795
+					revents=POLLIN | 
796
+						(((int)!(h->kq_array[r].flags & EV_EOF)-1)&POLLHUP);
797
+					while(fm->type && (fm->events & revents) && 
798
+							(handle_io(fm, revents, -1)>0) && repeat);
799
+				}else if (h->kq_array[r].filter==EVFILT_WRITE){
800
+					revents=POLLOUT | 
801
+						(((int)!(h->kq_array[r].flags & EV_EOF)-1)&POLLHUP);
802
+					while(fm->type && (fm->events & revents) && 
803
+							(handle_io(fm, revents, -1)>0) && repeat);
804
+				}
793 805
 			}
794 806
 		}
795 807
 error:
... ...
@@ -810,12 +1065,14 @@ inline static int io_wait_loop_sigio_rt(io_wait_h* h, int t)
810 810
 	int sigio_band;
811 811
 	int sigio_fd;
812 812
 	struct fd_map* fm;
813
+	int revents;
813 814
 	
814 815
 	
815 816
 	ret=1; /* 1 event per call normally */
816 817
 	ts.tv_sec=t;
817 818
 	ts.tv_nsec=0;
818
-	if (!sigismember(&h->sset, h->signo) || !sigismember(&h->sset, SIGIO)){
819
+	if (unlikely(!sigismember(&h->sset, h->signo) ||
820
+					!sigismember(&h->sset, SIGIO))) {
819 821
 		LOG(L_CRIT, "BUG: io_wait_loop_sigio_rt: the signal mask"
820 822
 				" is not properly set!\n");
821 823
 		goto error;
... ...
@@ -823,7 +1080,7 @@ inline static int io_wait_loop_sigio_rt(io_wait_h* h, int t)
823 823
 
824 824
 again:
825 825
 	n=sigtimedwait(&h->sset, &siginfo, &ts);
826
-	if (n==-1){
826
+	if (unlikely(n==-1)){
827 827
 		if (errno==EINTR) goto again; /* some other signal, ignore it */
828 828
 		else if (errno==EAGAIN){ /* timeout */
829 829
 			ret=0;
... ...
@@ -834,7 +1091,7 @@ again:
834 834
 			goto error;
835 835
 		}
836 836
 	}
837
-	if (n!=SIGIO){
837
+	if (likely(n!=SIGIO)){
838 838
 #ifdef SIGINFO64_WORKARROUND
839 839
 		/* on linux siginfo.si_band is defined as long in userspace
840 840
 		 * and as int in kernel (< 2.6.5) => on 64 bits things will break!
... ...
@@ -853,7 +1110,7 @@ again:
853 853
 			sigio_band=siginfo.si_band;
854 854
 			sigio_fd=siginfo.si_fd;
855 855
 		}
856
-		if (siginfo.si_code==SI_SIGIO){
856
+		if (unlikely(siginfo.si_code==SI_SIGIO)){
857 857
 			/* old style, we don't know the event (linux 2.2.?) */
858 858
 			LOG(L_WARN, "WARNING: io_wait_loop_sigio_rt: old style sigio"
859 859
 					" interface\n");
... ...
@@ -861,7 +1118,7 @@ again:
861 861
 			/* we can have queued signals generated by fds not watched
862 862
 			 * any more, or by fds in transition, to a child => ignore them*/
863 863
 			if (fm->type)
864
-				handle_io(fm, -1);
864
+				handle_io(fm, POLLIN|POLLOUT, -1);
865 865
 		}else{
866 866
 #ifdef EXTRA_DEBUG
867 867
 			DBG("io_wait_loop_sigio_rt: siginfo: signal=%d (%d),"
... ...
@@ -874,13 +1131,17 @@ again:
874 874
 			/* on some errors (e.g. when receving TCP RST), sigio_band will
875 875
 			 * be set to 0x08 (undocumented, no corresp. POLL_xx), so better
876 876
 			 * catch all events --andrei */
877
-			if (sigio_band/*&(POLL_IN|POLL_ERR|POLL_HUP)*/){
877
+			if (likely(sigio_band)/*&(POLL_IN|POLL_ERR|POLL_HUP)*/){
878 878
 				fm=get_fd_map(h, sigio_fd);
879
+				revents=(POLLIN & (!(sigio_band & POLL_IN)-1)) |
880
+						(POLLOUT & (!(sigio_band & POLL_OUT)-1)) |
881
+						(POLLERR & (!(sigio_band & POLL_ERR)-1)) |
882
+						(POLLHUP & (!(sigio_band & POLL_HUP)-1));
879 883
 				/* we can have queued signals generated by fds not watched
880 884
 			 	 * any more, or by fds in transition, to a child 
881 885
 				 * => ignore them */
882
-				if (fm->type)
883
-					handle_io(fm, -1);
886
+				if (fm->type && (fm->events & revents))
887
+					handle_io(fm, revents, -1);
884 888
 				else
885 889
 					LOG(L_ERR, "WARNING: io_wait_loop_sigio_rt: ignoring event"
886 890
 							" %x on fd %d (fm->fd=%d, fm->data=%p)\n",
... ...
@@ -930,7 +1191,7 @@ inline static int io_wait_loop_devpoll(io_wait_h* h, int t, int repeat)
930 930
 		dpoll.dp_fds=h->fd_array;
931 931
 again:
932 932
 		ret=n=ioctl(h->dpoll_fd, DP_POLL, &dpoll);
933
-		if (n==-1){
933
+		if (unlikely(n==-1)){
934 934
 			if (errno==EINTR) goto again; /* signal, ignore it */
935 935
 			else{
936 936
 				LOG(L_ERR, "ERROR:io_wait_loop_devpoll: ioctl: %s [%d]\n",
... ...
@@ -946,7 +1207,8 @@ again:
946 946
 			}
947 947
 			/* POLLIN|POLLHUP just go through */
948 948
 			fm=get_fd_map(h, h->fd_array[r].fd);
949
-			while(fm->type && (handle_io(fm, r) > 0) && repeat);
949
+			while(fm->type && (fm->events & h->fd_array[r].revents) &&
950
+					(handle_io(fm, h->fd_array[r].revents, r) > 0) && repeat);
950 951
 		}
951 952
 error:
952 953
 	return ret;
... ...
@@ -1730,7 +1730,8 @@ inline static int handle_tcp_child(struct tcp_child* tcp_c, int fd_i)
1730 1730
 			/* must be after the de-ref*/
1731 1731
 			tcpconn->flags&=~(F_CONN_REMOVED|F_CONN_READER);
1732 1732
 			if (unlikely(
1733
-					io_watch_add(&io_h, tcpconn->s, F_TCPCONN, tcpconn)<0)){
1733
+					io_watch_add(&io_h, tcpconn->s, POLLIN,
1734
+												F_TCPCONN, tcpconn)<0)){
1734 1735
 				LOG(L_CRIT, "ERROR: tcp_main: handle_tcp_child: failed to add"
1735 1736
 						" new socket to the fd list\n");
1736 1737
 				tcpconn->flags|=F_CONN_REMOVED;
... ...
@@ -1879,7 +1880,8 @@ inline static int handle_ser_child(struct process_table* p, int fd_i)
1879 1879
 								tcp_con_lifetime, t);
1880 1880
 			tcpconn->flags&=~F_CONN_REMOVED;
1881 1881
 			if (unlikely(
1882
-					io_watch_add(&io_h, tcpconn->s, F_TCPCONN, tcpconn)<0)){
1882
+					io_watch_add(&io_h, tcpconn->s, POLLIN,
1883
+												F_TCPCONN, tcpconn)<0)){
1883 1884
 				LOG(L_CRIT, "ERROR: tcp_main: handle_ser_child: failed to add"
1884 1885
 						" new socket to the fd list\n");
1885 1886
 				tcpconn->flags|=F_CONN_REMOVED;
... ...
@@ -2036,7 +2038,8 @@ static inline int handle_new_connect(struct socket_info* si)
2036 2036
 		local_timer_add(&tcp_main_ltimer, &tcpconn->timer, 
2037 2037
 								tcp_con_lifetime, get_ticks_raw());
2038 2038
 		tcpconn->flags&=~F_CONN_REMOVED;
2039
-		if (unlikely(io_watch_add(&io_h, tcpconn->s, F_TCPCONN, tcpconn)<0)){
2039
+		if (unlikely(io_watch_add(&io_h, tcpconn->s, POLLIN, 
2040
+													F_TCPCONN, tcpconn)<0)){
2040 2041
 			LOG(L_CRIT, "ERROR: tcp_main: handle_new_connect: failed to add"
2041 2042
 						" new socket to the fd list\n");
2042 2043
 			tcpconn->flags|=F_CONN_REMOVED;
... ...
@@ -2128,7 +2131,7 @@ error:
2128 2128
  *         >0 on successfull read from the fd (when there might be more io
2129 2129
  *            queued -- the receive buffer might still be non-empty)
2130 2130
  */
2131
-inline static int handle_io(struct fd_map* fm, int idx)
2131
+inline static int handle_io(struct fd_map* fm, short events, int idx)
2132 2132
 {	
2133 2133
 	int ret;
2134 2134
 	
... ...
@@ -2310,7 +2313,7 @@ void tcp_main_loop()
2310 2310
 	/* add all the sockets we listen on for connections */
2311 2311
 	for (si=tcp_listen; si; si=si->next){
2312 2312
 		if ((si->proto==PROTO_TCP) &&(si->socket!=-1)){
2313
-			if (io_watch_add(&io_h, si->socket, F_SOCKINFO, si)<0){
2313
+			if (io_watch_add(&io_h, si->socket, POLLIN, F_SOCKINFO, si)<0){
2314 2314
 				LOG(L_CRIT, "ERROR: tcp_main_loop: init: failed to add "
2315 2315
 							"listen socket to the fd list\n");
2316 2316
 				goto error;
... ...
@@ -2323,7 +2326,7 @@ void tcp_main_loop()
2323 2323
 	if (!tls_disable && tls_loaded()){
2324 2324
 		for (si=tls_listen; si; si=si->next){
2325 2325
 			if ((si->proto==PROTO_TLS) && (si->socket!=-1)){
2326
-				if (io_watch_add(&io_h, si->socket, F_SOCKINFO, si)<0){
2326
+				if (io_watch_add(&io_h, si->socket, POLLIN, F_SOCKINFO, si)<0){
2327 2327
 					LOG(L_CRIT, "ERROR: tcp_main_loop: init: failed to add "
2328 2328
 							"tls listen socket to the fd list\n");
2329 2329
 					goto error;
... ...
@@ -2339,7 +2342,7 @@ void tcp_main_loop()
2339 2339
 	 *  (get fd, new connection a.s.o) */
2340 2340
 	for (r=1; r<process_no; r++){
2341 2341
 		if (pt[r].unix_sock>0) /* we can't have 0, we never close it!*/
2342
-			if (io_watch_add(&io_h, pt[r].unix_sock, F_PROC, &pt[r])<0){
2342
+			if (io_watch_add(&io_h, pt[r].unix_sock, POLLIN,F_PROC, &pt[r])<0){
2343 2343
 					LOG(L_CRIT, "ERROR: tcp_main_loop: init: failed to add "
2344 2344
 							"process %d unix socket to the fd list\n", r);
2345 2345
 					goto error;
... ...
@@ -2348,8 +2351,8 @@ void tcp_main_loop()
2348 2348
 	/* add all the unix sokets used for communication with the tcp childs */
2349 2349
 	for (r=0; r<tcp_children_no; r++){
2350 2350
 		if (tcp_children[r].unix_sock>0)/*we can't have 0, we never close it!*/
2351
-			if (io_watch_add(&io_h, tcp_children[r].unix_sock, F_TCPCHILD,
2352
-							&tcp_children[r]) <0){
2351
+			if (io_watch_add(&io_h, tcp_children[r].unix_sock, POLLIN,
2352
+									F_TCPCHILD, &tcp_children[r]) <0){
2353 2353
 				LOG(L_CRIT, "ERROR: tcp_main_loop: init: failed to add "
2354 2354
 						"tcp child %d unix socket to the fd list\n", r);
2355 2355
 				goto error;
... ...
@@ -56,6 +56,7 @@ void init_tcp_options()
56 56
 	if (tcp_options.option){\
57 57
 		WARN("tcp_options: tcp_" ##option \
58 58
 				"cannot be enabled (recompile needed)\n"); \
59
+		tcp_options.option=0; \
59 60
 	}
60 61
 
61 62
 
... ...
@@ -64,6 +65,7 @@ void init_tcp_options()
64 64
 	if (tcp_options.option){\
65 65
 		WARN("tcp_options: tcp_" ##option \
66 66
 				"cannot be enabled (no OS support)\n"); \
67
+		tcp_options.option=0; \
67 68
 	}
68 69
 
69 70
 
... ...
@@ -718,7 +718,7 @@ static ticks_t tcpconn_read_timeout(ticks_t t, struct timer_ln* tl, void* data)
718 718
  *         >0 on successfull read from the fd (when there might be more io
719 719
  *            queued -- the receive buffer might still be non-empty)
720 720
  */
721
-inline static int handle_io(struct fd_map* fm, int idx)
721
+inline static int handle_io(struct fd_map* fm, short events, int idx)
722 722
 {	
723 723
 	int ret;
724 724
 	int n;
... ...
@@ -778,7 +778,7 @@ again:
778 778
 			timer_reinit(&con->timer);
779 779
 			local_timer_add(&tcp_reader_ltimer, &con->timer,
780 780
 								S_TO_TICKS(TCP_CHILD_TIMEOUT), t);
781
-			if (unlikely(io_watch_add(&io_w, s, F_TCPCONN, con))<0){
781
+			if (unlikely(io_watch_add(&io_w, s, POLLIN, F_TCPCONN, con))<0){
782 782
 				LOG(L_CRIT, "ERROR: tcp_receive: handle_io: failed to add"
783 783
 						" new socket to the fd list\n");
784 784
 				tcpconn_listrm(tcp_conn_lst, con, c_next, c_prev);
... ...
@@ -845,7 +845,7 @@ void tcp_receive_loop(int unix_sock)
845 845
 	if (init_local_timer(&tcp_reader_ltimer, get_ticks_raw())!=0)
846 846
 		goto error;
847 847
 	/* add the unix socket */
848
-	if (io_watch_add(&io_w, tcpmain_sock, F_TCPMAIN, 0)<0){
848
+	if (io_watch_add(&io_w, tcpmain_sock, POLLIN,  F_TCPMAIN, 0)<0){
849 849
 		LOG(L_CRIT, "ERROR: tcp_receive_loop: init: failed to add socket "
850 850
 							" to the fd list\n");
851 851
 		goto error;