Remove pthread.h from source. We should be using asterisk/lock.h everywhere instead...
[asterisk/asterisk.git] / utils.c
diff --git a/utils.c b/utils.c
index df06881..66ac2e2 100755 (executable)
--- a/utils.c
+++ b/utils.c
@@ -9,22 +9,26 @@
  * the GNU General Public License
  */
 
+#include <ctype.h>
+#include <string.h>
+#include <unistd.h>
 #include <asterisk/lock.h>
 #include <asterisk/utils.h>
 
-#if defined(__FreeBSD__)
+#if defined(__FreeBSD__) || defined(__OpenBSD__)
 
 /* duh? ERANGE value copied from web... */
 #define ERANGE 34
 #undef gethostbyname
 
-int gethostbyname_r (const char *name, struct hostent *ret, char *buf,
-                       size_t buflen, struct hostent **result, 
-                       int *h_errnop) 
+AST_MUTEX_DEFINE_STATIC(__mutex);
+
+static int gethostbyname_r (const char *name, struct hostent *ret, char *buf,
+                            size_t buflen, struct hostent **result, 
+                            int *h_errnop) 
 {
        int hsave;
        struct hostent *ph;
-       static ast_mutex_t __mutex = AST_MUTEX_INITIALIZER;
        ast_mutex_lock(&__mutex); /* begin critical area */
        hsave = h_errno;
 
@@ -110,7 +114,7 @@ int gethostbyname_r (const char *name, struct hostent *ret, char *buf,
        h_errno = hsave;  /* restore h_errno */
        ast_mutex_unlock(&__mutex); /* end critical area */
 
-       return (*result != NULL);
+       return (*result == NULL); /* return 0 on success, non-zero on error */
 }
 
 
@@ -120,11 +124,80 @@ struct hostent *ast_gethostbyname(const char *host, struct ast_hostent *hp)
 {
        int res;
        int herrno;
+       const char *s;
        struct hostent *result = NULL;
-
+       /* Although it is perfectly legitimate to lookup a pure integer, for
+          the sake of the sanity of people who like to name their peers as
+          integers, we break with tradition and refuse to look up a
+          pure integer */
+       s = host;
+       while(s && *s) {
+               if (!isdigit(*s))
+                       break;
+               s++;
+       }
+       if (!s || !*s)
+               return NULL;
        res = gethostbyname_r(host, &hp->hp, hp->buf, sizeof(hp->buf), &result, &herrno);
 
-       if (res || !hp->hp.h_addr_list || !hp->hp.h_addr_list[0])
+       if (res || !result || !hp->hp.h_addr_list || !hp->hp.h_addr_list[0])
                return NULL;
        return &hp->hp;
 }
+
+
+/* This is a regression test for recursive mutexes.
+   test_for_thread_safety() will return 0 if recursive mutex locks are
+   working properly, and non-zero if they are not working properly. */
+
+AST_MUTEX_DEFINE_STATIC(test_lock);
+AST_MUTEX_DEFINE_STATIC(test_lock2);
+static pthread_t test_thread; 
+static int lock_count = 0;
+static int test_errors = 0;
+
+static void *test_thread_body(void *data) 
+{ 
+  ast_mutex_lock(&test_lock);
+  lock_count += 10;
+  if(lock_count != 10) test_errors++;
+  ast_mutex_lock(&test_lock);
+  lock_count += 10;
+  if(lock_count != 20) test_errors++;
+  ast_mutex_lock(&test_lock2);
+  ast_mutex_unlock(&test_lock);
+  lock_count -= 10;
+  if(lock_count != 10) test_errors++;
+  ast_mutex_unlock(&test_lock);
+  lock_count -= 10;
+  ast_mutex_unlock(&test_lock2);
+  if(lock_count != 0) test_errors++;
+  return NULL;
+} 
+
+int test_for_thread_safety(void)
+{ 
+  ast_mutex_lock(&test_lock2);
+  ast_mutex_lock(&test_lock);
+  lock_count += 1;
+  ast_mutex_lock(&test_lock);
+  lock_count += 1;
+  pthread_create(&test_thread, NULL, test_thread_body, NULL); 
+  pthread_yield();
+  usleep(100);
+  if(lock_count != 2) test_errors++;
+  ast_mutex_unlock(&test_lock);
+  lock_count -= 1;
+  pthread_yield(); 
+  usleep(100); 
+  if(lock_count != 1) test_errors++;
+  ast_mutex_unlock(&test_lock);
+  lock_count -= 1;
+  if(lock_count != 0) test_errors++;
+  ast_mutex_unlock(&test_lock2);
+  pthread_yield();
+  usleep(100);
+  if(lock_count != 0) test_errors++;
+  pthread_join(test_thread, NULL);
+  return(test_errors);          /* return 0 on success. */
+}