[eglib] Replace strerror with strerror_r as the former is not thread safe.
authorRodrigo Kumpera <kumpera@gmail.com>
Tue, 13 Jun 2017 20:40:34 +0000 (13:40 -0700)
committerRodrigo Kumpera <kumpera@gmail.com>
Tue, 13 Jun 2017 20:40:34 +0000 (13:40 -0700)
This change would be nicer if the code was moved to the runtime so we could use our PAL.

eglib/configure.ac
eglib/src/gstr.c

index 92cd6156f94a94c466ada7cc817befedab309b57..b043298e3da0e45cf9f86c314e653742c7f44544 100644 (file)
@@ -141,7 +141,7 @@ AC_CHECK_SIZEOF(int)
 AC_CHECK_SIZEOF(void *)
 AC_CHECK_SIZEOF(long)
 AC_CHECK_SIZEOF(long long)
-AC_CHECK_FUNCS(strlcpy stpcpy strtok_r rewinddir vasprintf)
+AC_CHECK_FUNCS(strlcpy stpcpy strtok_r rewinddir vasprintf strerror_r)
 AC_CHECK_FUNCS(getrlimit)
 AC_CHECK_FUNCS(fork execv execve)
 
index 8b64da572f69967e7c17f459cafcf2beb2b8e55c..77464e42c4866f11c008fac295a0a3b9307d1622 100644 (file)
 #include <ctype.h>
 #include <glib.h>
 
+#ifndef G_OS_WIN32
+#include <pthread.h>
+#endif
+
 /* 
  * g_strndup and g_vasprintf need to allocate memory with g_malloc if 
  * ENABLE_OVERRIDABLE_ALLOCATORS is defined so that it can be safely freed with g_free 
@@ -191,10 +195,56 @@ g_strdup_printf (const gchar *format, ...)
        return ret;
 }
 
+
+/*
+Max error number we support. It's empirically found by looking at our target OS.
+
+Last this was checked was June-2017.
+
+Apple is at 106.
+Android is at 133.
+*/
+#define MONO_ERRNO_MAX 200
+#define str(s) #s
+
+#ifndef G_OS_WIN32
+static pthread_mutex_t strerror_lock = PTHREAD_MUTEX_INITIALIZER;
+#endif
+
+static char *error_messages [MONO_ERRNO_MAX];
+
 const gchar *
 g_strerror (gint errnum)
 {
-       return strerror (errnum);
+       if (errnum < 0)
+               errnum = -errnum;
+       if (errnum >= MONO_ERRNO_MAX)
+               return ("Error number higher than " str (MONO_ERRNO_MAX));
+
+       if (!error_messages [errnum]) {
+#ifndef G_OS_WIN32
+               pthread_mutex_lock (&strerror_lock);
+#endif
+
+#ifdef HAVE_STRERROR_R
+               char tmp_buff [128]; //Quite arbritrary
+               tmp_buff [0] = 0;
+
+               strerror_r (errnum, tmp_buff, sizeof (tmp_buff) - 1); //Spec is not clean on whether size argument includes space for null terminator or not
+               if (!error_messages [errnum])
+                       error_messages [errnum] = g_strdup (tmp_buff);
+#else
+               if (!error_messages [errnum])
+                       error_messages [errnum] = g_strdup_printf ("Error code '%d'", errnum);
+#endif
+
+
+#ifndef G_OS_WIN32
+               pthread_mutex_unlock (&strerror_lock);
+#endif
+
+       }
+       return error_messages [errnum];
 }
 
 gchar *