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 55
 VERSION = 0
56 56
 PATCHLEVEL = 10
57 57
 SUBLEVEL =   99
58
-EXTRAVERSION = -dev8-new_tcp
58
+EXTRAVERSION = -dev9-new_tcp
59 59
 
60 60
 RELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
61 61
 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 63
 			-e s/armv4l/arm/ -e "s/Power Macintosh/ppc/" -e "s/cobalt/mips2/" \
64 64
 			-e s/amd64/x86_64/ )
65 65
 OSREL = $(shell uname -r)
66
+# numerical version (good for comparisons: A.B.C => A*1000000+B*1000+C)
67
+OSREL_N= $(shell echo $(OSREL) | sed -e 's/^[^0-9]*//' \
68
+		-e 's/^\([0-9][0-9]*\(\.[0-9][0-9]*\)*\).*$$/\1/g' | \
69
+		(IFS=. read A B C ; R=0; \
70
+		[ -n "$$A" ] && R=`expr $$R \* 1000 + $$A` && \
71
+		[ -n "$$B" ] && R=`expr $$R \* 1000 + $$B` && \
72
+		[ -n "$$C" ] && R=`expr $$R \* 1000 + $$C`; echo $$R ) )
66 73
 
67 74
 # TLS support
68 75
 TLS ?= 
... ...
@@ -913,14 +921,17 @@ ifeq ($(OS), linux)
913 913
 		DEFS+= -DUSE_SYSV_SEM  # try posix sems
914 914
 		found_lock_method=yes
915 915
 	endif
916
-	# check for 2.6
917
-	ifneq ($(shell echo "$(OSREL)"|grep "^2\.6\."),)
916
+	# check for >= 2.5.44
917
+	ifeq ($(shell [ $(OSREL_N) -ge 2005044 ] && echo has_epoll), has_epoll)
918 918
 		ifeq ($(NO_EPOLL),)
919 919
 			DEFS+=-DHAVE_EPOLL
920 920
 		endif
921 921
 	endif
922
-	ifeq ($(NO_SIGIO),)
923
-		DEFS+=-DHAVE_SIGIO_RT
922
+	# check for >= 2.2.0
923
+	ifeq ($(shell [ $(OSREL_N) -ge 2002000 ] && echo has_sigio), has_sigio)
924
+		ifeq ($(NO_SIGIO),)
925
+			DEFS+=-DHAVE_SIGIO_RT
926
+		endif
924 927
 	endif
925 928
 	ifeq ($(NO_SELECT),)
926 929
 		DEFS+=-DHAVE_SELECT
... ...
@@ -971,6 +982,12 @@ ifeq ($(OS), freebsd)
971 971
 	else
972 972
 		LIBS= -lfl  #dlopen is in libc
973 973
 	endif
974
+	# check for ver >= 4.1
975
+	ifeq ($(shell [ $(OSREL_N) -gt 4001 ] && echo has_kqueue), has_kqueue)
976
+		ifeq ($(NO_KQUEUE),)
977
+			DEFS+=-DHAVE_KQUEUE
978
+		endif
979
+	endif
974 980
 	ifeq ($(NO_SELECT),)
975 981
 		DEFS+=-DHAVE_SELECT
976 982
 	endif
... ...
@@ -984,6 +1001,12 @@ ifeq ($(OS), openbsd)
984 984
 		DEFS+= -DUSE_PTHREAD_MUTEX  # try pthread sems
985 985
 		found_lock_method=yes
986 986
 	endif
987
+	# check for ver >= 3.7
988
+	ifeq ($(shell [ $(OSREL_N) -ge 3007 ] && echo has_kqueue), has_kqueue)
989
+		ifeq ($(NO_KQUEUE),)
990
+			DEFS+=-DHAVE_KQUEUE
991
+		endif
992
+	endif
987 993
 	ifeq ($(NO_SELECT),)
988 994
 		DEFS+=-DHAVE_SELECT
989 995
 	endif
... ...
@@ -1016,6 +1039,13 @@ ifeq ($(OS), netbsd)
1016 1016
 		DEFS+= -DUSE_SYSV_SEM  # try pthread sems
1017 1017
 		found_lock_method=yes
1018 1018
 	endif
1019
+	# check for ver >= 2.0.0
1020
+$(warning OSREL_N=$(OSREL_N) , OSREL=$(OSREL) )
1021
+	ifeq ($(shell [ $(OSREL_N) -ge 2000000 ] && echo has_kqueue), has_kqueue)
1022
+		ifeq ($(NO_KQUEUE),)
1023
+			DEFS+=-DHAVE_KQUEUE
1024
+		endif
1025
+	endif
1019 1026
 	ifeq ($(NO_SELECT),)
1020 1027
 		DEFS+=-DHAVE_SELECT
1021 1028
 	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 216
 
217 217
 
218 218
 
219
+#ifdef HAVE_KQUEUE
220
+/* kqueue specific init
221
+ * returns -1 on error, 0 on success */
222
+static int init_kqueue(io_wait_h* h)
223
+{
224
+	h->kq_fd=kqueue();
225
+	if (h->kq_fd==-1){
226
+		LOG(L_ERR, "ERROR: init_kqueue: kqueue: %s [%d]\n",
227
+				strerror(errno), errno);
228
+		return -1;
229
+	}
230
+	return 0;
231
+}
232
+
233
+
234
+
235
+static void destroy_kqueue(io_wait_h* h)
236
+{
237
+	if (h->kq_fd!=-1){
238
+		close(h->kq_fd);
239
+		h->kq_fd=-1;
240
+	}
241
+}
242
+#endif
243
+
244
+
245
+
219 246
 #ifdef HAVE_SELECT
220 247
 static int init_select(io_wait_h* h)
221 248
 {
... ...
@@ -284,10 +312,10 @@ char* check_poll_method(enum poll_types poll_method)
284 284
 			break;
285 285
 		case POLL_EPOLL_LT:
286 286
 		case POLL_EPOLL_ET:
287
-			/* only on 2.6 + */
288 287
 #ifndef HAVE_EPOLL
289 288
 			ret="epoll not supported, try re-compiling with -DHAVE_EPOLL";
290 289
 #else
290
+			/* only on 2.6 + */
291 291
 			if (os_ver<0x020542) /* if ver < 2.5.66 */
292 292
 			 	ret="epoll not supported on kernels < 2.6";
293 293
 #endif
... ...
@@ -296,8 +324,30 @@ char* check_poll_method(enum poll_types poll_method)
296 296
 #ifndef HAVE_SIGIO_RT
297 297
 			ret="sigio_rt not supported, try re-compiling with"
298 298
 				" -DHAVE_SIGIO_RT";
299
+#else
300
+			/* only on 2.2 +  ?? */
301
+			if (os_ver<0x020200) /* if ver < 2.2.0 */
302
+			 	ret="epoll not supported on kernels < 2.2 (?)";
299 303
 #endif
300 304
 			break;
305
+		case POLL_KQUEUE:
306
+#ifndef HAVE_KQUEUE
307
+			ret="kqueue not supported, try re-compiling with -DHAVE_KQUEUE";
308
+#else
309
+		/* only in FreeBSD 4.1, NETBSD 2.0, OpenBSD ???, Darwin ??? FIXME */
310
+	#ifdef __OS_freebsd
311
+			if (os_ver<0x0401) /* if ver < 4.1 */
312
+				ret="kqueue not supported on FreeBSD < 4.1";
313
+	#elif defined (__OS_netbsd)
314
+			if (os_ver<0x020000) /* if ver < 2.0 */
315
+				ret="kqueue not supported on NetBSD < 2.0";
316
+	#elif defined (__OS_openbsd)
317
+			if (os_ver<0x0307) /* if ver < 3.7 ??? */
318
+				ret="kqueue not supported on OpenBSD < 3.7 (?)";
319
+	#endif /* assume that the rest support kqueue ifdef HAVE_KQUEUE */
320
+#endif
321
+			break;	
322
+
301 323
 		default:
302 324
 			ret="unknown not supported method";
303 325
 	}
... ...
@@ -318,8 +368,22 @@ enum poll_types choose_poll_method()
318 318
 		poll_method=POLL_EPOLL_LT; /* or POLL_EPOLL_ET */
319 319
 		
320 320
 #endif
321
+#ifdef HAVE_KQUEUE
322
+	if (poll_method==0)
323
+		/* only in FreeBSD 4.1, NETBSD 2.0, OpenBSD ???, Darwin ??? FIXME */
324
+	#ifdef __OS_freebsd
325
+		if (os_ver>=0x0401) /* if ver >= 4.1 */
326
+	#elif defined (__OS_netbsd)
327
+		if (os_ver>=0x020000) /* if ver >= 2.0 */
328
+	#elif defined (__OS_openbsd)
329
+		if (os_ver>=0x0307) /* if ver >= 3.7 */
330
+	#endif /* assume that the rest support kqueue ifdef HAVE_KQUEUE */
331
+			poll_method=POLL_KQUEUE;
332
+#endif
321 333
 #ifdef  HAVE_SIGIO_RT
322
-		if (poll_method==0) poll_method=POLL_SIGIO_RT;
334
+		if (poll_method==0) 
335
+			if (os_ver>=0x020200) /* if ver >= 2.2.0 */
336
+				poll_method=POLL_SIGIO_RT;
323 337
 #endif
324 338
 		if (poll_method==0) poll_method=POLL_POLL;
325 339
 	return poll_method;
... ...
@@ -369,7 +433,9 @@ int init_io_wait(io_wait_h* h, int max_fd, enum poll_types poll_method)
369 369
 #ifdef HAVE_EPOLL
370 370
 	h->epfd=-1;
371 371
 #endif
372
-	
372
+#ifdef HAVE_KQUEUE
373
+	h->kq_fd=-1;
374
+#endif
373 375
 	poll_err=check_poll_method(poll_method);
374 376
 	
375 377
 	/* set an appropiate poll method */
... ...
@@ -446,6 +512,32 @@ int init_io_wait(io_wait_h* h, int max_fd, enum poll_types poll_method)
446 446
 			}
447 447
 			break;
448 448
 #endif
449
+#ifdef HAVE_KQUEUE
450
+		case POLL_KQUEUE:
451
+			h->kq_array=local_malloc(sizeof(*(h->kq_array))*h->max_fd_no);
452
+			if (h->kq_array==0){
453
+				LOG(L_CRIT, "ERROR: init_io_wait: could not alloc"
454
+							" kqueue event array\n");
455
+				goto error;
456
+			}
457
+			h->kq_changes_size=KQ_CHANGES_ARRAY_SIZE;
458
+			h->kq_changes=local_malloc(sizeof(*(h->kq_changes))*
459
+										h->kq_changes_size);
460
+			if (h->kq_changes==0){
461
+				LOG(L_CRIT, "ERROR: init_io_wait: could not alloc"
462
+							" kqueue changes array\n");
463
+				goto error;
464
+			}
465
+			h->kq_nchanges=0;
466
+			memset((void*)h->kq_array, 0, sizeof(*(h->kq_array))*h->max_fd_no);
467
+			memset((void*)h->kq_changes, 0,
468
+						sizeof(*(h->kq_changes))* h->kq_changes_size);
469
+			if (init_kqueue(h)<0){
470
+				LOG(L_CRIT, "ERROR: init_io_wait: kqueue init failed\n");
471
+				goto error;
472
+			}
473
+			break;
474
+#endif
449 475
 		default:
450 476
 			LOG(L_CRIT, "BUG: init_io_wait: unknown/unsupported poll"
451 477
 						" method %s (%d)\n",
... ...
@@ -473,6 +565,19 @@ void destroy_io_wait(io_wait_h* h)
473 473
 			}
474 474
 		break;
475 475
 #endif
476
+#ifdef HAVE_KQUEUE
477
+		case POLL_KQUEUE:
478
+			destroy_kqueue(h);
479
+			if (h->kq_array){
480
+				local_free(h->kq_array);
481
+				h->kq_array=0;
482
+			}
483
+			if (h->kq_changes){
484
+				local_free(h->kq_changes);
485
+				h->kq_changes=0;
486
+			}
487
+			break;
488
+#endif
476 489
 #ifdef HAVE_SIGIO_RT
477 490
 		case POLL_SIGIO_RT:
478 491
 			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 64
 #ifdef HAVE_EPOLL
65 65
 #include <sys/epoll.h>
66 66
 #endif
67
+#ifdef HAVE_KQUEUE
68
+#include <sys/types.h> /* needed on freebsd */
69
+#include <sys/event.h>
70
+#include <sys/time.h>
71
+#endif
67 72
 #ifdef HAVE_SELECT
68 73
 /* needed on openbsd for select*/
69 74
 #include <sys/time.h> 
... ...
@@ -103,6 +109,19 @@ struct fd_map{
103 103
 };
104 104
 
105 105
 
106
+#ifdef HAVE_KQUEUE
107
+#ifndef KQ_CHANGES_ARRAY_SIZE
108
+#define KQ_CHANGES_ARRAY_SIZE 128
109
+
110
+#ifdef __OS_netbsd
111
+#define KEV_UDATA_CAST (intptr_t)
112
+#else
113
+#define KEV_UDATA_CAST
114
+#endif
115
+
116
+#endif
117
+#endif
118
+
106 119
 
107 120
 /* handler structure */
108 121
 struct io_wait_handler{
... ...
@@ -114,6 +133,13 @@ struct io_wait_handler{
114 114
 	sigset_t sset; /* signal mask for sigio & sigrtmin */
115 115
 	int signo;     /* real time signal used */
116 116
 #endif
117
+#ifdef HAVE_KQUEUE
118
+	struct kevent* kq_array;   /* used for the eventlist*/
119
+	struct kevent* kq_changes; /* used for the changelist */
120
+	size_t kq_nchanges;
121
+	size_t kq_changes_size; /* size of the changes array */
122
+	int kq_fd;
123
+#endif
117 124
 #ifdef HAVE_SELECT
118 125
 	fd_set master_set;
119 126
 	int max_fd_select; /* maximum select used fd */
... ...
@@ -185,6 +211,43 @@ int handle_io(struct fd_map* fm, int idx);
185 185
 
186 186
 
187 187
 
188
+#ifdef HAVE_KQUEUE
189
+/*
190
+ * kqueue specific function: register a change
191
+ * (adds a change to the kevent change array, and if full flushes it first)
192
+ * returns: -1 on error, 0 on success
193
+ */
194
+static inline int kq_ev_change(io_wait_h* h, int fd, int filter, int flag, 
195
+								void* data)
196
+{
197
+	int n;
198
+	struct timespec tspec;
199
+
200
+	if (h->kq_nchanges>=h->kq_changes_size){
201
+		/* changes array full ! */
202
+		LOG(L_WARN, "WARNING: kq_ev_change: kqueue changes array full"
203
+					" trying to flush...\n");
204
+		tspec.tv_sec=0;
205
+		tspec.tv_nsec=0;
206
+again:
207
+		n=kevent(h->kq_fd, h->kq_changes, h->kq_nchanges, 0, 0, &tspec);
208
+		if (n==-1){
209
+			if (errno==EINTR) goto again;
210
+			LOG(L_ERR, "ERROR: io_watch_add: kevent flush changes "
211
+						" failed: %s [%d]\n", strerror(errno), errno);
212
+			return -1;
213
+		}
214
+		h->kq_nchanges=0; /* changes array is empty */
215
+	}
216
+	EV_SET(&h->kq_changes[h->kq_nchanges], fd, filter, flag, 0, 0,
217
+			KEV_UDATA_CAST data);
218
+	h->kq_nchanges++;
219
+	return 0;
220
+}
221
+#endif
222
+
223
+
224
+
188 225
 /* generic io_watch_add function
189 226
  * returns 0 on success, -1 on error
190 227
  *
... ...
@@ -235,7 +298,7 @@ inline static int io_watch_add(	io_wait_h* h,
235 235
 		LOG(L_CRIT, "BUG: io_watch_add: fd is -1!\n");
236 236
 		goto error;
237 237
 	}
238
-	/* add it to the poll fd array */
238
+	/* check if not too big */
239 239
 	if (h->fd_no>=h->max_fd_no){
240 240
 		LOG(L_CRIT, "ERROR: io_watch_add: maximum fd number exceeded:"
241 241
 				" %d/%d\n", h->fd_no, h->max_fd_no);
... ...
@@ -321,6 +384,12 @@ again2:
321 321
 			}
322 322
 			break;
323 323
 #endif
324
+#ifdef HAVE_KQUEUE
325
+		case POLL_KQUEUE:
326
+			if (kq_ev_change(h, fd, EVFILT_READ, EV_ADD, e)==-1)
327
+				goto error;
328
+			break;
329
+#endif
324 330
 		default:
325 331
 			LOG(L_CRIT, "BUG: io_watch_add: no support for poll method "
326 332
 					" %s (%d)\n", poll_method_str[h->poll_method],
... ...
@@ -328,7 +397,7 @@ again2:
328 328
 			goto error;
329 329
 	}
330 330
 	
331
-	h->fd_no++; /* "activate" changes, for epoll it
331
+	h->fd_no++; /* "activate" changes, for epoll/kqueue/devpoll it
332 332
 				   has only informative value */
333 333
 	return 0;
334 334
 error:
... ...
@@ -339,12 +408,19 @@ error:
339 339
 
340 340
 
341 341
 
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
342
+#define IO_FD_CLOSING 16
343
+/* parameters:    h - handler 
344
+ *               fd - file descriptor
345
+ *            index - index in the fd_array if known, -1 if not
346
+ *                    (if index==-1 fd_array will be searched for the
347
+ *                     corresponding fd* entry -- slower but unavoidable in 
348
+ *                     some cases). index is not used (no fd_array) for epoll,
349
+ *                     /dev/poll and kqueue
350
+ *            flags - optimization flags, e.g. IO_FD_CLOSING, the fd was 
351
+ *                    or will shortly be closed, in some cases we can avoid
352
+ *                    extra remove operations (e.g.: epoll, kqueue, sigio)
346 353
  * returns 0 if ok, -1 on error */
347
-inline static int io_watch_del(io_wait_h* h, int fd, int idx)
354
+inline static int io_watch_del(io_wait_h* h, int fd, int idx, int flags)
348 355
 {
349 356
 	
350 357
 #define fix_fd_array \
... ...
@@ -416,11 +492,21 @@ inline static int io_watch_del(io_wait_h* h, int fd, int idx)
416 416
 #ifdef HAVE_EPOLL
417 417
 		case POLL_EPOLL_LT:
418 418
 		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;
419
+			if (!(flags & IO_FD_CLOSING)){
420
+				n=epoll_ctl(h->epfd, EPOLL_CTL_DEL, fd, &ep_event);
421
+				if (n==-1){
422
+					LOG(L_ERR, "ERROR: io_watch_del: removing fd from epoll "
423
+							"list failed: %s [%d]\n", strerror(errno), errno);
424
+					goto error;
425
+				}
426
+			}
427
+			break;
428
+#endif
429
+#ifdef HAVE_KQUEUE
430
+		case POLL_KQUEUE:
431
+			if (!(flags & IO_FD_CLOSING)){
432
+				if (kq_ev_change(h, fd, EVFILT_READ, EV_DELETE, 0)==-1)
433
+					goto error;
424 434
 			}
425 435
 			break;
426 436
 #endif
... ...
@@ -528,7 +614,7 @@ again:
528 528
 		if (n==-1){
529 529
 			if (errno==EINTR) goto again; /* signal, ignore it */
530 530
 			else{
531
-				LOG(L_ERR, "ERROR:io_wait_loop_epoll_et: epoll_wait:"
531
+				LOG(L_ERR, "ERROR:io_wait_loop_epoll: epoll_wait:"
532 532
 						" %s [%d]\n", strerror(errno), errno);
533 533
 				goto error;
534 534
 			}
... ...
@@ -544,6 +630,47 @@ error:
544 544
 
545 545
 
546 546
 
547
+#ifdef HAVE_KQUEUE
548
+inline static int io_wait_loop_kqueue(io_wait_h* h, int t, int repeat)
549
+{
550
+	int n, r;
551
+	struct timespec tspec;
552
+	
553
+	tspec.tv_sec=t;
554
+	tspec.tv_nsec=0;
555
+again:
556
+		n=kevent(h->kq_fd, h->kq_changes, h->kq_nchanges,  h->kq_array,
557
+					h->fd_no, &tspec);
558
+		if (n==-1){
559
+			if (errno==EINTR) goto again; /* signal, ignore it */
560
+			else{
561
+				LOG(L_ERR, "ERROR: io_wait_loop_kqueue: kevent:"
562
+						" %s [%d]\n", strerror(errno), errno);
563
+				goto error;
564
+			}
565
+		}
566
+		h->kq_nchanges=0; /* reset changes array */
567
+		for (r=0; r<n; r++){
568
+			if (h->kq_array[r].flags & EV_ERROR){
569
+				/* error in changes: we ignore it, it can be caused by
570
+				   trying to remove an already closed fd: race between
571
+				   adding smething to the changes array, close() and
572
+				   applying the changes */
573
+				LOG(L_INFO, "INFO: io_wait_loop_kqueue: kevent error on "
574
+							"fd %d: %s [%d]\n", h->kq_array[r].ident,
575
+							strerror(h->kq_array[r].data),
576
+							h->kq_array[r].data);
577
+			}else /* READ/EOF */
578
+				while((handle_io((struct fd_map*)h->kq_array[r].udata, -1)>0)
579
+						&& repeat);
580
+		}
581
+error:
582
+	return n;
583
+}
584
+#endif
585
+
586
+
587
+
547 588
 #ifdef HAVE_SIGIO_RT
548 589
 /* sigio rt version has no repeat (it doesn't make sense)*/
549 590
 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 1073
 	}
1074 1074
 	/* pass it to child, so remove it from the io watch list */
1075 1075
 	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;
1076
+	if (io_watch_del(&io_h, tcpconn->s, fd_i, 0)==-1) goto error;
1077 1077
 	tcpconn_ref(tcpconn); /* refcnt ++ */
1078 1078
 	if (send2child(tcpconn)<0){
1079 1079
 		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 1126
 			DBG("DBG: handle_tcp_child: dead tcp child %d (pid %d, no %d)"
1127 1127
 					" (shutting down?)\n", (int)(tcp_c-&tcp_children[0]), 
1128 1128
 					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); 
1129
+			/* don't listen on it any more */
1130
+			io_watch_del(&io_h, tcp_c->unix_sock, fd_i, 0); 
1131 1131
 			goto error; /* eof. so no more io here, it's ok to return error */
1132 1132
 		}else if (bytes<0){
1133 1133
 			/* 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 1186
 				tcp_c->busy--;
1187 1187
 				/* main doesn't listen on it => we don't have to delete it
1188 1188
 				 if (tcpconn->s!=-1)
1189
-					io_watch_del(&io_h, tcpconn->s, -1);
1189
+					io_watch_del(&io_h, tcpconn->s, -1, IO_FD_CLOSING);
1190 1190
 				*/
1191
-				tcpconn_destroy(tcpconn);
1191
+				tcpconn_destroy(tcpconn); /* closes also the fd */
1192 1192
 				break;
1193 1193
 		default:
1194 1194
 				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 1244
 			DBG("DBG: handle_ser_child: dead child %d, pid %d"
1245 1245
 					" (shutting down?)\n", (int)(p-&pt[0]), p->pid);
1246 1246
 			/* don't listen on it any more */
1247
-			io_watch_del(&io_h, p->unix_sock, fd_i);
1247
+			io_watch_del(&io_h, p->unix_sock, fd_i, 0);
1248 1248
 			goto error; /* child dead => no further io events from it */
1249 1249
 		}else if (bytes<0){
1250 1250
 			/* 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 1283
 	switch(cmd){
1284 1284
 		case CONN_ERROR:
1285 1285
 			if (tcpconn->s!=-1)
1286
-				io_watch_del(&io_h, tcpconn->s, -1);
1287
-			tcpconn_destroy(tcpconn);
1286
+				io_watch_del(&io_h, tcpconn->s, -1, IO_FD_CLOSING);
1287
+			tcpconn_destroy(tcpconn); /* will close also the fd */
1288 1288
 			break;
1289 1289
 		case CONN_GET_FD:
1290 1290
 			/* send the requested FD  */
... ...
@@ -1391,7 +1392,7 @@ static void tcpconn_timeout()
1391 1391
 #endif
1392 1392
 				_tcpconn_rm(c);
1393 1393
 				if (fd>0) {
1394
-					io_watch_del(&io_h, fd, -1);
1394
+					io_watch_del(&io_h, fd, -1, IO_FD_CLOSING);
1395 1395
 					close(fd);
1396 1396
 				}
1397 1397
 			}
... ...
@@ -1507,6 +1508,14 @@ void tcp_main_loop()
1507 1507
 			}
1508 1508
 			break;
1509 1509
 #endif
1510
+#ifdef HAVE_KQUEUE
1511
+		case POLL_KQUEUE:
1512
+			while(1){
1513
+				io_wait_loop_kqueue(&io_h, TCP_MAIN_SELECT_TIMEOUT, 0);
1514
+				tcpconn_timeout();
1515
+			}
1516
+			break;
1517
+#endif
1510 1518
 		default:
1511 1519
 			LOG(L_CRIT, "BUG: tcp_main_loop: no support for poll method "
1512 1520
 					" %s (%d)\n", 
... ...
@@ -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 319
 	if (addr->s.sa_family==AF_INET){
320 320
 		if (setsockopt(sock_info->socket, IPPROTO_IP, IP_MULTICAST_LOOP, 
321 321
 						&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;
322
+			LOG(L_WARN, "WARNING: udp_init: setsockopt(IP_MULTICAST_LOOP):"
323
+						" %s\n", strerror(errno));
324
+			/* it's only a warning because we might get this error if the
325
+			  network interface doesn't support multicasting -- andrei */
325 326
 		}
326 327
 		if (mcast_ttl>=0){
327 328
 			if (setsockopt(sock_info->socket, IPPROTO_IP, IP_MULTICAST_TTL,
328 329
 						&mcast_ttl, sizeof(mcast_ttl))==-1){
329
-				LOG(L_ERR, "ERROR: udp_init: setsockopt (IP_MULTICAST_TTL):"
330
+				LOG(L_WARN, "WARNING: udp_init: setsockopt (IP_MULTICAST_TTL):"
330 331
 						" %s\n", strerror(errno));
331
-				goto error;
332 332
 			}
333 333
 		}
334 334
 #ifdef USE_IPV6
335 335
 	} else if (addr->s.sa_family==AF_INET6){
336 336
 		if (setsockopt(sock_info->socket, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, 
337 337
 						&mcast_loopback, sizeof(mcast_loopback))==-1){
338
-			LOG(L_ERR, "ERROR: udp_init: setsockopt (IPV6_MULTICAST_LOOP):"
338
+			LOG(L_WARN, "WARNING: udp_init: setsockopt (IPV6_MULTICAST_LOOP):"
339 339
 					" %s\n", strerror(errno));
340
-			goto error;
341 340
 		}
342 341
 		if (mcast_ttl>=0){
343 342
 			if (setsockopt(sock_info->socket, IPPROTO_IP, IPV6_MULTICAST_HOPS,
344 343
 							&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;
344
+				LOG(L_WARN, "WARNING: udp_init: setssckopt "
345
+						"(IPV6_MULTICAST_HOPS): %s\n", strerror(errno));
348 346
 			}
349 347
 		}
350 348
 #endif /* USE_IPV6*/