Explorar o código

totemudp: Retry if bind fails

If bind call fails it's retried for BIND_MAX_RETRIES.
If it's still unsuccessful, corosync exists instead
of working incorrectly.

Slightly modified by reviewer.

Signed-off-by: Masse Nicolas <nicolas.masse@stormshield.eu>
Reviewed-by: Jan Friesse <jfriesse@redhat.com>
Masse Nicolas %!s(int64=8) %!d(string=hai) anos
pai
achega
5b38aa721a
Modificáronse 3 ficheiros con 90 adicións e 10 borrados
  1. 62 8
      exec/totemudp.c
  2. 24 2
      exec/totemudpu.c
  3. 4 0
      include/corosync/totem/totem.h

+ 62 - 8
exec/totemudp.c

@@ -679,8 +679,9 @@ static int totemudp_build_sockets_ip (
 	struct sockaddr_in  *mcast_sin = (struct sockaddr_in *)&mcast_ss;
 	struct sockaddr_in  *boundto_sin = (struct sockaddr_in *)&boundto_ss;
 	unsigned int sendbuf_size;
-        unsigned int recvbuf_size;
-        unsigned int optlen = sizeof (sendbuf_size);
+	unsigned int recvbuf_size;
+	unsigned int optlen = sizeof (sendbuf_size);
+	unsigned int retries;
 	int addrlen;
 	int res;
 	int flag;
@@ -766,10 +767,25 @@ static int totemudp_build_sockets_ip (
 
 	totemip_totemip_to_sockaddr_convert(bound_to, instance->totem_interface->ip_port - 1,
 		&sockaddr, &addrlen);
-	res = bind (sockets->mcast_send, (struct sockaddr *)&sockaddr, addrlen);
-	if (res == -1) {
+
+	retries = 0;
+	while (1) {
+		res = bind (sockets->mcast_send, (struct sockaddr *)&sockaddr, addrlen);
+		if (res == 0) {
+			break;
+		}
 		LOGSYS_PERROR (errno, instance->totemudp_log_level_warning,
 			"Unable to bind the socket to send multicast packets");
+		if (++retries > BIND_MAX_RETRIES) {
+			break;
+		}
+
+		/*
+		 * Wait for a while
+		 */
+		(void)poll(NULL, 0, BIND_RETRIES_INTERVAL * retries);
+	}
+	if (res == -1) {
 		return (-1);
 	}
 
@@ -806,10 +822,25 @@ static int totemudp_build_sockets_ip (
 	 * This has the side effect of binding to the correct interface
 	 */
 	totemip_totemip_to_sockaddr_convert(bound_to, instance->totem_interface->ip_port, &sockaddr, &addrlen);
-	res = bind (sockets->token, (struct sockaddr *)&sockaddr, addrlen);
-	if (res == -1) {
+
+	retries = 0;
+	while (1) {
+		res = bind (sockets->token, (struct sockaddr *)&sockaddr, addrlen);
+		if (res == 0) {
+			break;
+		}
 		LOGSYS_PERROR (errno, instance->totemudp_log_level_warning,
 			"Unable to bind UDP unicast socket");
+		if (++retries > BIND_MAX_RETRIES) {
+			break;
+		}
+
+		/*
+		 * Wait for a while
+		 */
+		(void)poll(NULL, 0, BIND_RETRIES_INTERVAL * retries);
+	}
+	if (res == -1) {
 		return (-1);
 	}
 
@@ -1005,10 +1036,26 @@ static int totemudp_build_sockets_ip (
 	 */
 	totemip_totemip_to_sockaddr_convert(mcast_address,
 		instance->totem_interface->ip_port, &sockaddr, &addrlen);
-	res = bind (sockets->mcast_recv, (struct sockaddr *)&sockaddr, addrlen);
-	if (res == -1) {
+
+	retries = 0;
+	while (1) {
+		res = bind (sockets->mcast_recv, (struct sockaddr *)&sockaddr, addrlen);
+		if (res == 0) {
+			break;
+		}
 		LOGSYS_PERROR (errno, instance->totemudp_log_level_warning,
 				"Unable to bind the socket to receive multicast packets");
+		if (++retries > BIND_MAX_RETRIES) {
+			break;
+		}
+
+		/*
+		 * Wait for a while
+		 */
+		(void)poll(NULL, 0, BIND_RETRIES_INTERVAL * retries);
+	}
+
+	if (res == -1) {
 		return (-1);
 	}
 	return 0;
@@ -1043,6 +1090,13 @@ static int totemudp_build_sockets (
 	res = totemudp_build_sockets_ip (instance, mcast_address,
 		bindnet_address, sockets, bound_to, interface_num);
 
+	if (res == -1) {
+		/* if we get here, corosync won't work anyway, so better leaving than faking to work */
+		LOGSYS_PERROR (errno, instance->totemudp_log_level_error,
+			"Unable to create sockets, exiting");
+		exit(EXIT_FAILURE);
+	}
+
 	/* We only send out of the token socket */
 	totemudp_traffic_control_set(instance, sockets->token);
 	return res;

+ 24 - 2
exec/totemudpu.c

@@ -622,6 +622,7 @@ static int totemudpu_build_sockets_ip (
 	int res;
 	unsigned int recvbuf_size;
 	unsigned int optlen = sizeof (recvbuf_size);
+	unsigned int retries = 0;
 
 	/*
 	 * Setup unicast socket
@@ -646,10 +647,24 @@ static int totemudpu_build_sockets_ip (
 	 * This has the side effect of binding to the correct interface
 	 */
 	totemip_totemip_to_sockaddr_convert(bound_to, instance->totem_interface->ip_port, &sockaddr, &addrlen);
-	res = bind (instance->token_socket, (struct sockaddr *)&sockaddr, addrlen);
-	if (res == -1) {
+	while (1) {
+		res = bind (instance->token_socket, (struct sockaddr *)&sockaddr, addrlen);
+		if (res == 0) {
+			break;
+		}
 		LOGSYS_PERROR (errno, instance->totemudpu_log_level_warning,
 			"bind token socket failed");
+		if (++retries > BIND_MAX_RETRIES) {
+			break;
+		}
+
+		/*
+		 * Wait for a while
+		 */
+		(void)poll(NULL, 0, BIND_RETRIES_INTERVAL * retries);
+	}
+
+	if (res == -1) {
 		return (-1);
 	}
 
@@ -711,6 +726,13 @@ static int totemudpu_build_sockets (
 	res = totemudpu_build_sockets_ip (instance,
 		bindnet_address, bound_to, interface_num);
 
+	if (res == -1) {
+		/* if we get here, corosync won't work anyway, so better leaving than faking to work */
+		LOGSYS_PERROR (errno, instance->totemudpu_log_level_error,
+					"Unable to create sockets, exiting");
+		exit(EXIT_FAILURE);
+	}
+
 	/* We only send out of the token socket */
 	totemudpu_traffic_control_set(instance, instance->token_socket);
 

+ 4 - 0
include/corosync/totem/totem.h

@@ -55,6 +55,10 @@
 
 /* This must be <= KNET_MAX_LINK */
 #define INTERFACE_MAX		8
+
+#define BIND_MAX_RETRIES	10
+#define BIND_RETRIES_INTERVAL	100
+
 /**
  * Maximum number of continuous gather states
  */