[Asterisk-code-review] thread safety: Don't use getprotobyname() (asterisk[14])

Sean Bright asteriskteam at digium.com
Sat Mar 18 12:38:16 CDT 2017


Sean Bright has uploaded a new change for review. ( https://gerrit.asterisk.org/5250 )

Change subject: thread safety: Don't use getprotobyname()
......................................................................

thread safety: Don't use getprotobyname()

POSIX does not require getprotobyname() to be thread safe and some
implementations use static memory which causes issues when multiple
threads are used.

Further, our usage of it today is just to ultimately get IPPROTO_TCP
for calls to setsockopt(). So instead we just use IPPROTO_TCP directly.

Change-Id: I2e14e58674808f7ce99b2f5e900d0f90d0d8da48
---
M channels/chan_skinny.c
M include/asterisk/network.h
M main/http.c
M main/manager.c
4 files changed, 15 insertions(+), 28 deletions(-)


  git pull ssh://gerrit.asterisk.org:29418/asterisk refs/changes/50/5250/1

diff --git a/channels/chan_skinny.c b/channels/chan_skinny.c
index 56e6596..96a206c 100644
--- a/channels/chan_skinny.c
+++ b/channels/chan_skinny.c
@@ -7641,7 +7641,6 @@
 	struct sockaddr_in sin;
 	socklen_t sinlen;
 	struct skinnysession *s;
-	struct protoent *p;
 	int arg = 1;
 
 	for (;;) {
@@ -7658,12 +7657,10 @@
 			continue;
 		}
 
-		p = getprotobyname("tcp");
-		if(p) {
-			if( setsockopt(as, p->p_proto, TCP_NODELAY, (char *)&arg, sizeof(arg) ) < 0 ) {
-				ast_log(LOG_WARNING, "Failed to set Skinny tcp connection to TCP_NODELAY mode: %s\n", strerror(errno));
-			}
+		if (setsockopt(as, IPPROTO_TCP, TCP_NODELAY, (char *) &arg, sizeof(arg)) < 0) {
+			ast_log(LOG_WARNING, "Failed to set TCP_NODELAY on Skinny TCP connection: %s\n", strerror(errno));
 		}
+
 		if (!(s = ast_calloc(1, sizeof(struct skinnysession)))) {
 			close(as);
 			ast_atomic_fetchadd_int(&unauth_sessions, -1);
diff --git a/include/asterisk/network.h b/include/asterisk/network.h
index 3371e58..5216f4c 100644
--- a/include/asterisk/network.h
+++ b/include/asterisk/network.h
@@ -86,6 +86,11 @@
 #endif
 #define inet_ntoa __dont__use__inet_ntoa__use__ast_inet_ntoa__instead__
 
+#ifdef getprotobyname
+#undef getprotobyname
+#endif
+#define getprotobyname __getprotobyname_is_not_threadsafe__do_not_use__
+
 /*! \brief Compares the source address and port of two sockaddr_in */
 static force_inline int inaddrcmp(const struct sockaddr_in *sin1, const struct sockaddr_in *sin2)
 {
diff --git a/main/http.c b/main/http.c
index 5f308c3..737278a 100644
--- a/main/http.c
+++ b/main/http.c
@@ -1915,8 +1915,7 @@
 static void *httpd_helper_thread(void *data)
 {
 	struct ast_tcptls_session_instance *ser = data;
-	struct protoent *p;
-	int flags;
+	int flags = 1;
 	int timeout;
 
 	if (!ser || !ser->f) {
@@ -1936,16 +1935,8 @@
 	 * This is necessary to prevent delays (caused by buffering) as we
 	 * write to the socket in bits and pieces.
 	 */
-	p = getprotobyname("tcp");
-	if (p) {
-		int arg = 1;
-
-		if (setsockopt(ser->fd, p->p_proto, TCP_NODELAY, (char *) &arg, sizeof(arg) ) < 0) {
-			ast_log(LOG_WARNING, "Failed to set TCP_NODELAY on HTTP connection: %s\n", strerror(errno));
-			ast_log(LOG_WARNING, "Some HTTP requests may be slow to respond.\n");
-		}
-	} else {
-		ast_log(LOG_WARNING, "Failed to set TCP_NODELAY on HTTP connection, getprotobyname(\"tcp\") failed\n");
+	if (setsockopt(ser->fd, IPPROTO_TCP, TCP_NODELAY, (char *) &flags, sizeof(flags)) < 0) {
+		ast_log(LOG_WARNING, "Failed to set TCP_NODELAY on HTTP connection: %s\n", strerror(errno));
 		ast_log(LOG_WARNING, "Some HTTP requests may be slow to respond.\n");
 	}
 
diff --git a/main/manager.c b/main/manager.c
index 91b401c..102b4bd 100644
--- a/main/manager.c
+++ b/main/manager.c
@@ -6633,10 +6633,9 @@
 	struct mansession s = {
 		.tcptls_session = data,
 	};
-	int flags;
+	int flags = 1;
 	int res;
 	struct ast_sockaddr ser_remote_address_tmp;
-	struct protoent *p;
 
 	if (ast_atomic_fetchadd_int(&unauth_sessions, +1) >= authlimit) {
 		fclose(ser->f);
@@ -6656,14 +6655,9 @@
 	/* here we set TCP_NODELAY on the socket to disable Nagle's algorithm.
 	 * This is necessary to prevent delays (caused by buffering) as we
 	 * write to the socket in bits and pieces. */
-	p = getprotobyname("tcp");
-	if (p) {
-		int arg = 1;
-		if( setsockopt(ser->fd, p->p_proto, TCP_NODELAY, (char *)&arg, sizeof(arg) ) < 0 ) {
-			ast_log(LOG_WARNING, "Failed to set manager tcp connection to TCP_NODELAY mode: %s\nSome manager actions may be slow to respond.\n", strerror(errno));
-		}
-	} else {
-		ast_log(LOG_WARNING, "Failed to set manager tcp connection to TCP_NODELAY, getprotobyname(\"tcp\") failed\nSome manager actions may be slow to respond.\n");
+	if (setsockopt(ser->fd, IPPROTO_TCP, TCP_NODELAY, (char *) &flags, sizeof(flags)) < 0) {
+		ast_log(LOG_WARNING, "Failed to set TCP_NODELAY on manager connection: %s\n", strerror(errno));
+		ast_log(LOG_WARNING, "Some manager actions may be slow to respond.\n");
 	}
 
 	/* make sure socket is non-blocking */

-- 
To view, visit https://gerrit.asterisk.org/5250
To unsubscribe, visit https://gerrit.asterisk.org/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I2e14e58674808f7ce99b2f5e900d0f90d0d8da48
Gerrit-PatchSet: 1
Gerrit-Project: asterisk
Gerrit-Branch: 14
Gerrit-Owner: Sean Bright <sean.bright at gmail.com>



More information about the asterisk-code-review mailing list