Browse code

- kqueue support for freebsd, openbsd & netbsd added - failing to set multicast parameters is no longer an error (will not prevent ser from starting)

Andrei Pelinescu-Onciul authored on 26/06/2005 19:58:07
Showing 5 changed files
... ...
@@ -39,6 +39,7 @@
39 39
 #  2004-12-19  amd64 transformed in x86_64 (andrei)
40 40
 #  2005-04-27  alpha support added (andrei)
41 41
 #  2005-06-01  use $(LOCALBASE) instead of /usr/{local,pkg} (andrei)
42
+#  2006-06-26  numeric OSREL & HAVE_KQUEUE added to the *BSD (andrei)
42 43
 
43 44
 
44 45
 # check if already included/exported
... ...
@@ -55,7 +56,7 @@ MAIN_NAME=ser
55 56
 VERSION = 0
56 57
 PATCHLEVEL = 10
57 58
 SUBLEVEL =   99
58
-EXTRAVERSION = -dev8-new_tcp
59
+EXTRAVERSION = -dev9-new_tcp
59 60
 
60 61
 RELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
61 62
 OS = $(shell uname -s | sed -e s/SunOS/solaris/ | tr "[A-Z]" "[a-z]")
... ...
@@ -63,6 +64,13 @@ ARCH = $(shell uname -m |sed -e s/i.86/i386/ -e s/sun4u/sparc64/  \
63 64
 			-e s/armv4l/arm/ -e "s/Power Macintosh/ppc/" -e "s/cobalt/mips2/" \
64 65
 			-e s/amd64/x86_64/ )
65 66
 OSREL = $(shell uname -r)
67
+# numerical version (good for comparisons: A.B.C => A*1000000+B*1000+C)
68
+OSREL_N= $(shell echo $(OSREL) | sed -e 's/^[^0-9]*//' \
69
+		-e 's/^\([0-9][0-9]*\(\.[0-9][0-9]*\)*\).*$$/\1/g' | \
70
+		(IFS=. read A B C ; R=0; \
71
+		[ -n "$$A" ] && R=`expr $$R \* 1000 + $$A` && \
72
+		[ -n "$$B" ] && R=`expr $$R \* 1000 + $$B` && \
73
+		[ -n "$$C" ] && R=`expr $$R \* 1000 + $$C`; echo $$R ) )
66 74
 
67 75
 # TLS support
68 76
 TLS ?= 
... ...
@@ -913,14 +921,17 @@ ifeq ($(OS), linux)
913 921
 		DEFS+= -DUSE_SYSV_SEM  # try posix sems
914 922
 		found_lock_method=yes
915 923
 	endif
916
-	# check for 2.6
917
-	ifneq ($(shell echo "$(OSREL)"|grep "^2\.6\."),)
924
+	# check for >= 2.5.44
925
+	ifeq ($(shell [ $(OSREL_N) -ge 2005044 ] && echo has_epoll), has_epoll)
918 926
 		ifeq ($(NO_EPOLL),)
919 927
 			DEFS+=-DHAVE_EPOLL
920 928
 		endif
921 929
 	endif
922
-	ifeq ($(NO_SIGIO),)
923
-		DEFS+=-DHAVE_SIGIO_RT
930
+	# check for >= 2.2.0
931
+	ifeq ($(shell [ $(OSREL_N) -ge 2002000 ] && echo has_sigio), has_sigio)
932
+		ifeq ($(NO_SIGIO),)
933
+			DEFS+=-DHAVE_SIGIO_RT
934
+		endif
924 935
 	endif
925 936
 	ifeq ($(NO_SELECT),)
926 937
 		DEFS+=-DHAVE_SELECT
... ...
@@ -971,6 +982,12 @@ ifeq ($(OS), freebsd)
971 982
 	else
972 983
 		LIBS= -lfl  #dlopen is in libc
973 984
 	endif
985
+	# check for ver >= 4.1
986
+	ifeq ($(shell [ $(OSREL_N) -gt 4001 ] && echo has_kqueue), has_kqueue)
987
+		ifeq ($(NO_KQUEUE),)
988
+			DEFS+=-DHAVE_KQUEUE
989
+		endif
990
+	endif
974 991
 	ifeq ($(NO_SELECT),)
975 992
 		DEFS+=-DHAVE_SELECT
976 993
 	endif
... ...
@@ -984,6 +1001,12 @@ ifeq ($(OS), openbsd)
984 1001
 		DEFS+= -DUSE_PTHREAD_MUTEX  # try pthread sems
985 1002
 		found_lock_method=yes
986 1003
 	endif
1004
+	# check for ver >= 3.7
1005
+	ifeq ($(shell [ $(OSREL_N) -ge 3007 ] && echo has_kqueue), has_kqueue)
1006
+		ifeq ($(NO_KQUEUE),)
1007
+			DEFS+=-DHAVE_KQUEUE
1008
+		endif
1009
+	endif
987 1010
 	ifeq ($(NO_SELECT),)
988 1011
 		DEFS+=-DHAVE_SELECT
989 1012
 	endif
... ...
@@ -1016,6 +1039,13 @@ ifeq ($(OS), netbsd)
1016 1039
 		DEFS+= -DUSE_SYSV_SEM  # try pthread sems
1017 1040
 		found_lock_method=yes
1018 1041
 	endif
1042
+	# check for ver >= 2.0.0
1043
+$(warning OSREL_N=$(OSREL_N) , OSREL=$(OSREL) )
1044
+	ifeq ($(shell [ $(OSREL_N) -ge 2000000 ] && echo has_kqueue), has_kqueue)
1045
+		ifeq ($(NO_KQUEUE),)
1046
+			DEFS+=-DHAVE_KQUEUE
1047
+		endif
1048
+	endif
1019 1049
 	ifeq ($(NO_SELECT),)
1020 1050
 		DEFS+=-DHAVE_SELECT
1021 1051
 	endif
... ...
@@ -32,6 +32,7 @@
32 32
  * History:
33 33
  * --------
34 34
  *  2005-06-15  created by andrei
35
+ *  2005-06-26  added kqueue (andrei)
35 36
  */
36 37
 
37 38
 
... ...
@@ -216,6 +217,33 @@ static void destroy_epoll(io_wait_h* h)
216 217
 
217 218
 
218 219
 
220
+#ifdef HAVE_KQUEUE
221
+/* kqueue specific init
222
+ * returns -1 on error, 0 on success */
223
+static int init_kqueue(io_wait_h* h)
224
+{
225
+	h->kq_fd=kqueue();
226
+	if (h->kq_fd==-1){
227
+		LOG(L_ERR, "ERROR: init_kqueue: kqueue: %s [%d]\n",
228
+				strerror(errno), errno);
229
+		return -1;
230
+	}
231
+	return 0;
232
+}
233
+
234
+
235
+
236
+static void destroy_kqueue(io_wait_h* h)
237
+{
238
+	if (h->kq_fd!=-1){
239
+		close(h->kq_fd);
240
+		h->kq_fd=-1;
241
+	}
242
+}
243
+#endif
244
+
245
+
246
+
219 247
 #ifdef HAVE_SELECT
220 248
 static int init_select(io_wait_h* h)
221 249
 {
... ...
@@ -284,10 +312,10 @@ char* check_poll_method(enum poll_types poll_method)
284 312
 			break;
285 313
 		case POLL_EPOLL_LT:
286 314
 		case POLL_EPOLL_ET:
287
-			/* only on 2.6 + */
288 315
 #ifndef HAVE_EPOLL
289 316
 			ret="epoll not supported, try re-compiling with -DHAVE_EPOLL";
290 317
 #else
318
+			/* only on 2.6 + */
291 319
 			if (os_ver<0x020542) /* if ver < 2.5.66 */
292 320
 			 	ret="epoll not supported on kernels < 2.6";
293 321
 #endif
... ...
@@ -296,8 +324,30 @@ char* check_poll_method(enum poll_types poll_method)
296 324
 #ifndef HAVE_SIGIO_RT
297 325
 			ret="sigio_rt not supported, try re-compiling with"
298 326
 				" -DHAVE_SIGIO_RT";
327
+#else
328
+			/* only on 2.2 +  ?? */
329
+			if (os_ver<0x020200) /* if ver < 2.2.0 */
330
+			 	ret="epoll not supported on kernels < 2.2 (?)";
299 331
 #endif
300 332
 			break;
333
+		case POLL_KQUEUE:
334
+#ifndef HAVE_KQUEUE
335
+			ret="kqueue not supported, try re-compiling with -DHAVE_KQUEUE";
336
+#else
337
+		/* only in FreeBSD 4.1, NETBSD 2.0, OpenBSD ???, Darwin ??? FIXME */
338
+	#ifdef __OS_freebsd
339
+			if (os_ver<0x0401) /* if ver < 4.1 */
340
+				ret="kqueue not supported on FreeBSD < 4.1";
341
+	#elif defined (__OS_netbsd)
342
+			if (os_ver<0x020000) /* if ver < 2.0 */
343
+				ret="kqueue not supported on NetBSD < 2.0";
344
+	#elif defined (__OS_openbsd)
345
+			if (os_ver<0x0307) /* if ver < 3.7 ??? */
346
+				ret="kqueue not supported on OpenBSD < 3.7 (?)";
347
+	#endif /* assume that the rest support kqueue ifdef HAVE_KQUEUE */
348
+#endif
349
+			break;	
350
+
301 351
 		default:
302 352
 			ret="unknown not supported method";
303 353
 	}
... ...
@@ -318,8 +368,22 @@ enum poll_types choose_poll_method()
318 368
 		poll_method=POLL_EPOLL_LT; /* or POLL_EPOLL_ET */
319 369
 		
320 370
 #endif
371
+#ifdef HAVE_KQUEUE
372
+	if (poll_method==0)
373
+		/* only in FreeBSD 4.1, NETBSD 2.0, OpenBSD ???, Darwin ??? FIXME */
374
+	#ifdef __OS_freebsd
375
+		if (os_ver>=0x0401) /* if ver >= 4.1 */
376
+	#elif defined (__OS_netbsd)
377
+		if (os_ver>=0x020000) /* if ver >= 2.0 */
378
+	#elif defined (__OS_openbsd)
379
+		if (os_ver>=0x0307) /* if ver >= 3.7 */
380
+	#endif /* assume that the rest support kqueue ifdef HAVE_KQUEUE */
381
+			poll_method=POLL_KQUEUE;
382
+#endif
321 383
 #ifdef  HAVE_SIGIO_RT
322
-		if (poll_method==0) poll_method=POLL_SIGIO_RT;
384
+		if (poll_method==0) 
385
+			if (os_ver>=0x020200) /* if ver >= 2.2.0 */
386
+				poll_method=POLL_SIGIO_RT;
323 387
 #endif
324 388
 		if (poll_method==0) poll_method=POLL_POLL;
325 389
 	return poll_method;
... ...
@@ -369,7 +433,9 @@ int init_io_wait(io_wait_h* h, int max_fd, enum poll_types poll_method)
369 433
 #ifdef HAVE_EPOLL
370 434
 	h->epfd=-1;
371 435
 #endif
372
-	
436
+#ifdef HAVE_KQUEUE
437
+	h->kq_fd=-1;
438
+#endif
373 439
 	poll_err=check_poll_method(poll_method);
374 440
 	
375 441
 	/* set an appropiate poll method */
... ...
@@ -445,6 +511,32 @@ int init_io_wait(io_wait_h* h, int max_fd, enum poll_types poll_method)
445 511
 				goto error;
446 512
 			}
447 513
 			break;
514
+#endif
515
+#ifdef HAVE_KQUEUE
516
+		case POLL_KQUEUE:
517
+			h->kq_array=local_malloc(sizeof(*(h->kq_array))*h->max_fd_no);
518
+			if (h->kq_array==0){
519
+				LOG(L_CRIT, "ERROR: init_io_wait: could not alloc"
520
+							" kqueue event array\n");
521
+				goto error;
522
+			}
523
+			h->kq_changes_size=KQ_CHANGES_ARRAY_SIZE;
524
+			h->kq_changes=local_malloc(sizeof(*(h->kq_changes))*
525
+										h->kq_changes_size);
526
+			if (h->kq_changes==0){
527
+				LOG(L_CRIT, "ERROR: init_io_wait: could not alloc"
528
+							" kqueue changes array\n");
529
+				goto error;
530
+			}
531
+			h->kq_nchanges=0;
532
+			memset((void*)h->kq_array, 0, sizeof(*(h->kq_array))*h->max_fd_no);
533
+			memset((void*)h->kq_changes, 0,
534
+						sizeof(*(h->kq_changes))* h->kq_changes_size);
535
+			if (init_kqueue(h)<0){
536
+				LOG(L_CRIT, "ERROR: init_io_wait: kqueue init failed\n");
537
+				goto error;
538
+			}
539
+			break;
448 540
 #endif
449 541
 		default:
450 542
 			LOG(L_CRIT, "BUG: init_io_wait: unknown/unsupported poll"
... ...
@@ -473,6 +565,19 @@ void destroy_io_wait(io_wait_h* h)
473 565
 			}
474 566
 		break;
475 567
 #endif
568
+#ifdef HAVE_KQUEUE
569
+		case POLL_KQUEUE:
570
+			destroy_kqueue(h);
571
+			if (h->kq_array){
572
+				local_free(h->kq_array);
573
+				h->kq_array=0;
574
+			}
575
+			if (h->kq_changes){
576
+				local_free(h->kq_changes);
577
+				h->kq_changes=0;
578
+			}
579
+			break;
580
+#endif
476 581
 #ifdef HAVE_SIGIO_RT
477 582
 		case POLL_SIGIO_RT:
478 583
 			destroy_sigio(h);
... ...
@@ -46,6 +46,7 @@
46 46
  * History:
47 47
  * --------
48 48
  *  2005-06-13  created by andrei
49
+ *  2005-06-26  added kqueue (andrei)
49 50
  */
50 51
 
51 52
 
... ...
@@ -64,6 +65,11 @@
64 65
 #ifdef HAVE_EPOLL
65 66
 #include <sys/epoll.h>
66 67
 #endif
68
+#ifdef HAVE_KQUEUE
69
+#include <sys/types.h> /* needed on freebsd */
70
+#include <sys/event.h>
71
+#include <sys/time.h>
72
+#endif
67 73
 #ifdef HAVE_SELECT
68 74
 /* needed on openbsd for select*/
69 75
 #include <sys/time.h> 
... ...
@@ -103,6 +109,19 @@ struct fd_map{
103 109
 };
104 110
 
105 111
 
112
+#ifdef HAVE_KQUEUE
113
+#ifndef KQ_CHANGES_ARRAY_SIZE
114
+#define KQ_CHANGES_ARRAY_SIZE 128
115
+
116
+#ifdef __OS_netbsd
117
+#define KEV_UDATA_CAST (intptr_t)
118
+#else
119
+#define KEV_UDATA_CAST
120
+#endif
121
+
122
+#endif
123
+#endif
124
+
106 125
 
107 126
 /* handler structure */
108 127
 struct io_wait_handler{
... ...
@@ -114,6 +133,13 @@ struct io_wait_handler{
114 133
 	sigset_t sset; /* signal mask for sigio & sigrtmin */
115 134
 	int signo;     /* real time signal used */
116 135
 #endif
136
+#ifdef HAVE_KQUEUE
137
+	struct kevent* kq_array;   /* used for the eventlist*/
138
+	struct kevent* kq_changes; /* used for the changelist */
139
+	size_t kq_nchanges;
140
+	size_t kq_changes_size; /* size of the changes array */
141
+	int kq_fd;
142
+#endif
117 143
 #ifdef HAVE_SELECT
118 144
 	fd_set master_set;
119 145
 	int max_fd_select; /* maximum select used fd */
... ...
@@ -185,6 +211,43 @@ int handle_io(struct fd_map* fm, int idx);
185 211
 
186 212
 
187 213
 
214
+#ifdef HAVE_KQUEUE
215
+/*
216
+ * kqueue specific function: register a change
217
+ * (adds a change to the kevent change array, and if full flushes it first)
218
+ * returns: -1 on error, 0 on success
219
+ */
220
+static inline int kq_ev_change(io_wait_h* h, int fd, int filter, int flag, 
221
+								void* data)
222
+{
223
+	int n;
224
+	struct timespec tspec;
225
+
226
+	if (h->kq_nchanges>=h->kq_changes_size){
227
+		/* changes array full ! */
228
+		LOG(L_WARN, "WARNING: kq_ev_change: kqueue changes array full"
229
+					" trying to flush...\n");
230
+		tspec.tv_sec=0;
231
+		tspec.tv_nsec=0;
232
+again:
233
+		n=kevent(h->kq_fd, h->kq_changes, h->kq_nchanges, 0, 0, &tspec);
234
+		if (n==-1){
235
+			if (errno==EINTR) goto again;
236
+			LOG(L_ERR, "ERROR: io_watch_add: kevent flush changes "
237
+						" failed: %s [%d]\n", strerror(errno), errno);
238
+			return -1;
239
+		}
240
+		h->kq_nchanges=0; /* changes array is empty */
241
+	}
242
+	EV_SET(&h->kq_changes[h->kq_nchanges], fd, filter, flag, 0, 0,
243
+			KEV_UDATA_CAST data);
244
+	h->kq_nchanges++;
245
+	return 0;
246
+}
247
+#endif
248
+
249
+
250
+
188 251
 /* generic io_watch_add function
189 252
  * returns 0 on success, -1 on error
190 253
  *
... ...
@@ -235,7 +298,7 @@ inline static int io_watch_add(	io_wait_h* h,
235 298
 		LOG(L_CRIT, "BUG: io_watch_add: fd is -1!\n");
236 299
 		goto error;
237 300
 	}
238
-	/* add it to the poll fd array */
301
+	/* check if not too big */
239 302
 	if (h->fd_no>=h->max_fd_no){
240 303
 		LOG(L_CRIT, "ERROR: io_watch_add: maximum fd number exceeded:"
241 304
 				" %d/%d\n", h->fd_no, h->max_fd_no);
... ...
@@ -320,6 +383,12 @@ again2:
320 383
 				goto error;
321 384
 			}
322 385
 			break;
386
+#endif
387
+#ifdef HAVE_KQUEUE
388
+		case POLL_KQUEUE:
389
+			if (kq_ev_change(h, fd, EVFILT_READ, EV_ADD, e)==-1)
390
+				goto error;
391
+			break;
323 392
 #endif
324 393
 		default:
325 394
 			LOG(L_CRIT, "BUG: io_watch_add: no support for poll method "
... ...
@@ -328,7 +397,7 @@ again2:
328 397
 			goto error;
329 398
 	}
330 399
 	
331
-	h->fd_no++; /* "activate" changes, for epoll it
400
+	h->fd_no++; /* "activate" changes, for epoll/kqueue/devpoll it
332 401
 				   has only informative value */
333 402
 	return 0;
334 403
 error:
... ...
@@ -339,12 +408,19 @@ error:
339 408
 
340 409
 
341 410
 
342
-/* parameters: fd and index in the fd_array
343
- * if index==-1, it fd_array will be searched for the corresponding fd
344
- * entry (slower but unavoidable in some cases)
345
- * index is not used (no fd_arry) for epoll, /dev/poll and kqueue
411
+#define IO_FD_CLOSING 16
412
+/* parameters:    h - handler 
413
+ *               fd - file descriptor
414
+ *            index - index in the fd_array if known, -1 if not
415
+ *                    (if index==-1 fd_array will be searched for the
416
+ *                     corresponding fd* entry -- slower but unavoidable in 
417
+ *                     some cases). index is not used (no fd_array) for epoll,
418
+ *                     /dev/poll and kqueue
419
+ *            flags - optimization flags, e.g. IO_FD_CLOSING, the fd was 
420
+ *                    or will shortly be closed, in some cases we can avoid
421
+ *                    extra remove operations (e.g.: epoll, kqueue, sigio)
346 422
  * returns 0 if ok, -1 on error */
347
-inline static int io_watch_del(io_wait_h* h, int fd, int idx)
423
+inline static int io_watch_del(io_wait_h* h, int fd, int idx, int flags)
348 424
 {
349 425
 	
350 426
 #define fix_fd_array \
... ...
@@ -416,11 +492,21 @@ inline static int io_watch_del(io_wait_h* h, int fd, int idx)
416 492
 #ifdef HAVE_EPOLL
417 493
 		case POLL_EPOLL_LT:
418 494
 		case POLL_EPOLL_ET:
419
-			n=epoll_ctl(h->epfd, EPOLL_CTL_DEL, fd, &ep_event);
420
-			if (n==-1){
421
-				LOG(L_ERR, "ERROR: io_watch_del: removing fd from"
422
-					" epoll list failed: %s [%d]\n", strerror(errno), errno);
423
-				goto error;
495
+			if (!(flags & IO_FD_CLOSING)){
496
+				n=epoll_ctl(h->epfd, EPOLL_CTL_DEL, fd, &ep_event);
497
+				if (n==-1){
498
+					LOG(L_ERR, "ERROR: io_watch_del: removing fd from epoll "
499
+							"list failed: %s [%d]\n", strerror(errno), errno);
500
+					goto error;
501
+				}
502
+			}
503
+			break;
504
+#endif
505
+#ifdef HAVE_KQUEUE
506
+		case POLL_KQUEUE:
507
+			if (!(flags & IO_FD_CLOSING)){
508
+				if (kq_ev_change(h, fd, EVFILT_READ, EV_DELETE, 0)==-1)
509
+					goto error;
424 510
 			}
425 511
 			break;
426 512
 #endif
... ...
@@ -528,7 +614,7 @@ again:
528 614
 		if (n==-1){
529 615
 			if (errno==EINTR) goto again; /* signal, ignore it */
530 616
 			else{
531
-				LOG(L_ERR, "ERROR:io_wait_loop_epoll_et: epoll_wait:"
617
+				LOG(L_ERR, "ERROR:io_wait_loop_epoll: epoll_wait:"
532 618
 						" %s [%d]\n", strerror(errno), errno);
533 619
 				goto error;
534 620
 			}
... ...
@@ -544,6 +630,47 @@ error:
544 630
 
545 631
 
546 632
 
633
+#ifdef HAVE_KQUEUE
634
+inline static int io_wait_loop_kqueue(io_wait_h* h, int t, int repeat)
635
+{
636
+	int n, r;
637
+	struct timespec tspec;
638
+	
639
+	tspec.tv_sec=t;
640
+	tspec.tv_nsec=0;
641
+again:
642
+		n=kevent(h->kq_fd, h->kq_changes, h->kq_nchanges,  h->kq_array,
643
+					h->fd_no, &tspec);
644
+		if (n==-1){
645
+			if (errno==EINTR) goto again; /* signal, ignore it */
646
+			else{
647
+				LOG(L_ERR, "ERROR: io_wait_loop_kqueue: kevent:"
648
+						" %s [%d]\n", strerror(errno), errno);
649
+				goto error;
650
+			}
651
+		}
652
+		h->kq_nchanges=0; /* reset changes array */
653
+		for (r=0; r<n; r++){
654
+			if (h->kq_array[r].flags & EV_ERROR){
655
+				/* error in changes: we ignore it, it can be caused by
656
+				   trying to remove an already closed fd: race between
657
+				   adding smething to the changes array, close() and
658
+				   applying the changes */
659
+				LOG(L_INFO, "INFO: io_wait_loop_kqueue: kevent error on "
660
+							"fd %d: %s [%d]\n", h->kq_array[r].ident,
661
+							strerror(h->kq_array[r].data),
662
+							h->kq_array[r].data);
663
+			}else /* READ/EOF */
664
+				while((handle_io((struct fd_map*)h->kq_array[r].udata, -1)>0)
665
+						&& repeat);
666
+		}
667
+error:
668
+	return n;
669
+}
670
+#endif
671
+
672
+
673
+
547 674
 #ifdef HAVE_SIGIO_RT
548 675
 /* sigio rt version has no repeat (it doesn't make sense)*/
549 676
 inline static int io_wait_loop_sigio_rt(io_wait_h* h, int t)
... ...
@@ -54,6 +54,7 @@
54 54
  *  2004-11-08  dropped find_tcp_si and replaced with find_si (andrei)
55 55
  *  2005-06-07  new tcp optimized code, supports epoll (LT), sigio + real time
56 56
  *               signals, poll & select (andrei)
57
+ *  2005-06-26  *bsd kqueue support (andrei)
57 58
  */
58 59
 
59 60
 
... ...
@@ -1073,7 +1074,7 @@ inline static int handle_tcpconn_ev(struct tcp_connection* tcpconn, int fd_i)
1073 1074
 	}
1074 1075
 	/* pass it to child, so remove it from the io watch list */
1075 1076
 	DBG("handle_tcpconn_ev: data available on %p %d\n", tcpconn, tcpconn->s);
1076
-	if (io_watch_del(&io_h, tcpconn->s, fd_i)==-1) goto error;
1077
+	if (io_watch_del(&io_h, tcpconn->s, fd_i, 0)==-1) goto error;
1077 1078
 	tcpconn_ref(tcpconn); /* refcnt ++ */
1078 1079
 	if (send2child(tcpconn)<0){
1079 1080
 		LOG(L_ERR,"ERROR: handle_tcpconn_ev: no children available\n");
... ...
@@ -1126,8 +1127,8 @@ inline static int handle_tcp_child(struct tcp_child* tcp_c, int fd_i)
1126 1127
 			DBG("DBG: handle_tcp_child: dead tcp child %d (pid %d, no %d)"
1127 1128
 					" (shutting down?)\n", (int)(tcp_c-&tcp_children[0]), 
1128 1129
 					tcp_c->pid, tcp_c->proc_no );
1129
-						/* don't listen on it any more */
1130
-			io_watch_del(&io_h, tcp_c->unix_sock, fd_i); 
1130
+			/* don't listen on it any more */
1131
+			io_watch_del(&io_h, tcp_c->unix_sock, fd_i, 0); 
1131 1132
 			goto error; /* eof. so no more io here, it's ok to return error */
1132 1133
 		}else if (bytes<0){
1133 1134
 			/* EAGAIN is ok if we try to empty the buffer
... ...
@@ -1186,9 +1187,9 @@ inline static int handle_tcp_child(struct tcp_child* tcp_c, int fd_i)
1186 1187
 				tcp_c->busy--;
1187 1188
 				/* main doesn't listen on it => we don't have to delete it
1188 1189
 				 if (tcpconn->s!=-1)
1189
-					io_watch_del(&io_h, tcpconn->s, -1);
1190
+					io_watch_del(&io_h, tcpconn->s, -1, IO_FD_CLOSING);
1190 1191
 				*/
1191
-				tcpconn_destroy(tcpconn);
1192
+				tcpconn_destroy(tcpconn); /* closes also the fd */
1192 1193
 				break;
1193 1194
 		default:
1194 1195
 				LOG(L_CRIT, "BUG: handle_tcp_child:  unknown cmd %d"
... ...
@@ -1244,7 +1245,7 @@ inline static int handle_ser_child(struct process_table* p, int fd_i)
1244 1245
 			DBG("DBG: handle_ser_child: dead child %d, pid %d"
1245 1246
 					" (shutting down?)\n", (int)(p-&pt[0]), p->pid);
1246 1247
 			/* don't listen on it any more */
1247
-			io_watch_del(&io_h, p->unix_sock, fd_i);
1248
+			io_watch_del(&io_h, p->unix_sock, fd_i, 0);
1248 1249
 			goto error; /* child dead => no further io events from it */
1249 1250
 		}else if (bytes<0){
1250 1251
 			/* EAGAIN is ok if we try to empty the buffer
... ...
@@ -1283,8 +1284,8 @@ inline static int handle_ser_child(struct process_table* p, int fd_i)
1283 1284
 	switch(cmd){
1284 1285
 		case CONN_ERROR:
1285 1286
 			if (tcpconn->s!=-1)
1286
-				io_watch_del(&io_h, tcpconn->s, -1);
1287
-			tcpconn_destroy(tcpconn);
1287
+				io_watch_del(&io_h, tcpconn->s, -1, IO_FD_CLOSING);
1288
+			tcpconn_destroy(tcpconn); /* will close also the fd */
1288 1289
 			break;
1289 1290
 		case CONN_GET_FD:
1290 1291
 			/* send the requested FD  */
... ...
@@ -1391,7 +1392,7 @@ static void tcpconn_timeout()
1391 1392
 #endif
1392 1393
 				_tcpconn_rm(c);
1393 1394
 				if (fd>0) {
1394
-					io_watch_del(&io_h, fd, -1);
1395
+					io_watch_del(&io_h, fd, -1, IO_FD_CLOSING);
1395 1396
 					close(fd);
1396 1397
 				}
1397 1398
 			}
... ...
@@ -1506,6 +1507,14 @@ void tcp_main_loop()
1506 1507
 				tcpconn_timeout();
1507 1508
 			}
1508 1509
 			break;
1510
+#endif
1511
+#ifdef HAVE_KQUEUE
1512
+		case POLL_KQUEUE:
1513
+			while(1){
1514
+				io_wait_loop_kqueue(&io_h, TCP_MAIN_SELECT_TIMEOUT, 0);
1515
+				tcpconn_timeout();
1516
+			}
1517
+			break;
1509 1518
 #endif
1510 1519
 		default:
1511 1520
 			LOG(L_CRIT, "BUG: tcp_main_loop: no support for poll method "
... ...
@@ -35,6 +35,7 @@
35 35
  *  2004-07-05  udp_rcv_loop: drop packets with 0 src port + error msg.
36 36
  *              cleanups (andrei)
37 37
  *  2005-03-10  multicast options are now set for all the udp sockets (andrei)
38
+ *  2005-06-26  failure to set mcast options is not an error anymore (andrei)
38 39
  */
39 40
 
40 41
 
... ...
@@ -319,32 +320,30 @@ int udp_init(struct socket_info* sock_info)
319 320
 	if (addr->s.sa_family==AF_INET){
320 321
 		if (setsockopt(sock_info->socket, IPPROTO_IP, IP_MULTICAST_LOOP, 
321 322
 						&mcast_loopback, sizeof(mcast_loopback))==-1){
322
-			LOG(L_ERR, "ERROR: udp_init: setsockopt(IP_MULTICAST_LOOP): %s\n",
323
-						strerror(errno));
324
-			goto error;
323
+			LOG(L_WARN, "WARNING: udp_init: setsockopt(IP_MULTICAST_LOOP):"
324
+						" %s\n", strerror(errno));
325
+			/* it's only a warning because we might get this error if the
326
+			  network interface doesn't support multicasting -- andrei */
325 327
 		}
326 328
 		if (mcast_ttl>=0){
327 329
 			if (setsockopt(sock_info->socket, IPPROTO_IP, IP_MULTICAST_TTL,
328 330
 						&mcast_ttl, sizeof(mcast_ttl))==-1){
329
-				LOG(L_ERR, "ERROR: udp_init: setsockopt (IP_MULTICAST_TTL):"
331
+				LOG(L_WARN, "WARNING: udp_init: setsockopt (IP_MULTICAST_TTL):"
330 332
 						" %s\n", strerror(errno));
331
-				goto error;
332 333
 			}
333 334
 		}
334 335
 #ifdef USE_IPV6
335 336
 	} else if (addr->s.sa_family==AF_INET6){
336 337
 		if (setsockopt(sock_info->socket, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, 
337 338
 						&mcast_loopback, sizeof(mcast_loopback))==-1){
338
-			LOG(L_ERR, "ERROR: udp_init: setsockopt (IPV6_MULTICAST_LOOP):"
339
+			LOG(L_WARN, "WARNING: udp_init: setsockopt (IPV6_MULTICAST_LOOP):"
339 340
 					" %s\n", strerror(errno));
340
-			goto error;
341 341
 		}
342 342
 		if (mcast_ttl>=0){
343 343
 			if (setsockopt(sock_info->socket, IPPROTO_IP, IPV6_MULTICAST_HOPS,
344 344
 							&mcast_ttl, sizeof(mcast_ttl))==-1){
345
-				LOG(L_ERR, "ERROR: udp_init: setssckopt (IPV6_MULTICAST_HOPS):"
346
-						" %s\n", strerror(errno));
347
-				goto error;
345
+				LOG(L_WARN, "WARNING: udp_init: setssckopt "
346
+						"(IPV6_MULTICAST_HOPS): %s\n", strerror(errno));
348 347
 			}
349 348
 		}
350 349
 #endif /* USE_IPV6*/