[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

ipropd-master CLOSE_WAIT problem



Hi all!

On linux (I didn't tested other platforms) ipropd-master doesn't handle
tcp sockets well.
If an perviously connected replica disconnect from ipropd-master, then
ipropd-master  will not close the used tcp socket until the replica
reconnect again.
Because it the the tcp socket will be in CLOSE_WAIT state.
Because it the select func in every loop will report this socket
as activ and will never sleep, so ipropd-master will eat all the
CPU time until the replica reconnect.

The following patch correct the above problem for me on linux
platform. As I wrote I didn't tested it on other platforms and it can be
buggy, so it is only for demonstration purposes.

If possible correct the mainstream code.

Thanks.

balsa


diff -Naur heimdal-0.5.1-orig/lib/kadm5/ipropd_master.c heimdal-0.5.1/lib/kadm5/ipropd_master.c
--- heimdal-0.5.1-orig/lib/kadm5/ipropd_master.c	2002-08-16 20:27:53.000000000 +0200
+++ heimdal-0.5.1/lib/kadm5/ipropd_master.c	2003-03-13 03:19:21.000000000 +0100
@@ -87,6 +87,7 @@
     time_t seen;
     unsigned long flags;
 #define SLAVE_F_DEAD	0x1
+#define SLAVE_FD_CLOSED 0x2
     struct slave *next;
 };
 
@@ -132,7 +133,7 @@
 {
     slave **p;
 
-    if (s->fd >= 0)
+    if (!(s->flags & SLAVE_FD_CLOSED) && s->fd >= 0)
 	close (s->fd);
     if (s->name)
 	free (s->name);
@@ -371,6 +372,11 @@
     int32_t tmp;
 
     ret = krb5_read_priv_message(context, s->ac, &s->fd, &out);
+    if(ret == HEIM_ERR_EOF && close(s->fd) == 0) {
+	s->flags |= SLAVE_FD_CLOSED;
+	slave_dead(s);
+	return 1;
+    }
     if(ret) {
 	krb5_warn (context, ret, "error reading message from %s", s->name);
 	return 1;
@@ -566,8 +572,10 @@
 	max_fd = max(max_fd, listen_fd);
 
 	for (p = slaves; p != NULL; p = p->next) {
-	    FD_SET(p->fd, &readset);
-	    max_fd = max(max_fd, p->fd);
+	    if (!(p->flags & SLAVE_FD_CLOSED)) {
+		FD_SET(p->fd, &readset);
+	    	max_fd = max(max_fd, p->fd);
+	    }
 	}
 
 	ret = select (max_fd + 1,
@@ -605,7 +613,7 @@
 	}
 
 	for(p = slaves; ret && p != NULL; p = p->next)
-	    if (FD_ISSET(p->fd, &readset)) {
+	    if (!(p->flags & SLAVE_FD_CLOSED) && FD_ISSET(p->fd, &readset)) {
 		--ret;
 		if(process_msg (context, p, log_fd, database, current_version))
 		    slave_dead(p);