]> git.saurik.com Git - wxWidgets.git/blobdiff - src/unix/gsocket.cpp
Applied patch [ 1336712 ] Fix segfault when calling wxThread::Exit()
[wxWidgets.git] / src / unix / gsocket.cpp
index b4294370c14042e16660dd27e53b526a10231a41..1ea7b594e54ccf215eb632a5599c6e00c44cc67a 100644 (file)
@@ -181,6 +181,9 @@ int _System soclose(int);
 #  include "wx/unix/gsockunx.h"
 #  include "wx/unix/private.h"
 #  include "wx/gsocket.h"
+#if wxUSE_THREADS && (defined(HAVE_GETHOSTBYNAME) || defined(HAVE_GETSERVBYNAME))
+#  include "wx/thread.h"
+#endif
 #else
 #  include "gsockunx.h"
 #  include "gsocket.h"
@@ -189,6 +192,175 @@ int _System soclose(int);
 #  endif
 #endif /* __GSOCKET_STANDALONE__ */
 
+#if defined(HAVE_GETHOSTBYNAME)
+static struct hostent * deepCopyHostent(struct hostent *h,
+                                       const struct hostent *he,
+                                       char *buffer, int size, int *err)
+{
+  memcpy(h, he, sizeof(struct hostent));
+  int len = strlen(h->h_name);
+  if (len > size)
+    len = size - 1;
+  memcpy(buffer, h->h_name, len);
+  buffer[len] = '\0';
+  h->h_name = buffer;
+  buffer += len + 1;
+  size -= len + 1;
+  len = h->h_length;
+  for (char **p = h->h_addr_list; *p != 0; p++) {
+    if (size < len){
+      *err = ENOMEM;
+      return NULL;
+    }
+    memcpy(buffer, *p, len);
+    *p = buffer;
+    buffer += len;
+    size -= len;
+  }
+  for (char **q = h->h_aliases; size > 0 && *q != 0; q++){
+    len = strlen(*q);
+    if (len > size)
+      len = size - 1;
+    memcpy(buffer, *q, len);
+    buffer[len] = '\0';
+    *q = buffer;
+    buffer += len + 1;
+    size -= len + 1;
+  }
+  return h;
+}
+#endif
+
+struct hostent * wxGethostbyname_r(const char *hostname, struct hostent *h,
+                                  void *buffer, int size, int *err)
+
+{
+  struct hostent *he = NULL;
+  *err = 0;
+#if defined(HAVE_FUNC_GETHOSTBYNAME_R_6)
+  if (gethostbyname_r(hostname, h, (char*)buffer, size, &he, err))
+    he = NULL;
+#elif defined(HAVE_FUNC_GETHOSTBYNAME_R_5)
+  he = gethostbyname_r(hostname, h, (char*)buffer, size, err);
+#elif defined(HAVE_FUNC_GETHOSTBYNAME_R_3)
+  if (gethostbyname_r(hostname, h, (struct hostent_data*) buffer))
+  {
+    he = NULL;
+    *err = h_errno;
+  }
+  else
+    he = h;
+#elif defined(HAVE_GETHOSTBYNAME)
+#if wxUSE_THREADS
+  static wxMutex nameLock;
+  wxMutexLocker locker(nameLock);
+#endif
+  he = gethostbyname(hostname);
+  if (!he)
+    *err = h_errno;
+  else
+    he = deepCopyHostent(h, he, (char*)buffer, size, err);
+#endif
+  return he;
+}
+
+struct hostent * wxGethostbyaddr_r(const char *addr_buf, int buf_size,
+                                  int proto, struct hostent *h,
+                                  void *buffer, int size, int *err)
+{
+  struct hostent *he = NULL;
+  *err = 0;
+#if defined(HAVE_FUNC_GETHOSTBYNAME_R_6)
+  if (gethostbyaddr_r(addr_buf, buf_size, proto, h,
+                     (char*)buffer, size, &he, err))
+    he = NULL;
+#elif defined(HAVE_FUNC_GETHOSTBYNAME_R_5)
+  he = gethostbyaddr_r(addr_buf, buf_size, proto, h, (char*)buffer, size, err);
+#elif defined(HAVE_FUNC_GETHOSTBYNAME_R_3)
+  if (gethostbyaddr_r(addr_buf, buf_size, proto, h,
+                       (struct hostent_data*) buffer))
+  {
+    he = NULL;
+    *err = h_errno;
+  }
+  else
+    he = h;
+#elif defined(HAVE_GETHOSTBYNAME)
+#if wxUSE_THREADS
+  static wxMutex addrLock;
+  wxMutexLocker locker(addrLock);
+#endif
+  he = gethostbyaddr(addr_buf, buf_size, proto);
+  if (!he)
+    *err = h_errno;
+  else
+    he = deepCopyHostent(h, he, (char*)buffer, size, err);
+#endif
+  return he;
+}
+
+#if defined(HAVE_GETHOSTBYNAME)
+static struct servent * deepCopyServent(struct servent *s,
+                                       const struct servent *se,
+                                       char *buffer, int size)
+{
+  memcpy(s, se, sizeof(struct servent));
+  int len = strlen(s->s_name);
+  if (len > size)
+    len = size - 1;
+  memcpy(buffer, s->s_name, len);
+  buffer[len] = '\0';
+  s->s_name = buffer;
+  buffer += len + 1;
+  size -= len + 1;
+  len = strlen(s->s_proto);
+  if (len > size)
+    len = size - 1;
+  memcpy(buffer, s->s_proto, len);
+  buffer[len] = '\0';
+  s->s_proto = buffer;
+  buffer += len + 1;
+  size -= len + 1;
+  for (char **q = s->s_aliases; size > 0 && *q != 0; q++){
+    len = strlen(*q);
+    if (len > size)
+      len = size - 1;
+    memcpy(buffer, *q, len);
+    buffer[len] = '\0';
+    *q = buffer;
+    buffer += len + 1;
+    size -= len + 1;
+  }
+  return s;
+}
+#endif
+
+struct servent *wxGetservbyname_r(const char *port, const char *protocol,
+                                 struct servent *serv, void *buffer, int size)
+{
+  struct servent *se = NULL;
+#if defined(HAVE_FUNC_GETSERVBYNAME_R_6)
+  if (getservbyname_r(port, protocol, serv, (char*)buffer, size, &se))
+    se = NULL;
+#elif defined(HAVE_FUNC_GETSERVBYNAME_R_5)
+  se = getservbyname_r(port, protocol, serv, (char*)buffer, size);
+#elif defined(HAVE_FUNC_GETSERVBYNAME_R_4)
+  if (getservbyname_r(port, protocol, serv, (struct servent_data*) buffer))
+    se = NULL;
+  else
+    se = serv;
+#elif defined(HAVE_GETSERVBYNAME)
+#if wxUSE_THREADS
+  static wxMutex servLock;
+  wxMutexLocker locker(servLock);
+#endif
+  se = getservbyname(port, protocol);
+  if (se)
+    se = deepCopyServent(serv, se, (char*)buffer, size);
+#endif
+  return se;
+}
+
 /* debugging helpers */
 #ifdef __GSOCKET_DEBUG__
 #  define GSocket_Debug(args) printf args
@@ -1772,7 +1944,15 @@ GSocketError GAddress_INET_SetHostName(GAddress *address, const char *hostname)
     struct in_addr *array_addr;
 
     /* It is a real name, we solve it */
-    if ((he = gethostbyname(hostname)) == NULL)
+    struct hostent h;
+#if defined(HAVE_FUNC_GETHOSTBYNAME_R_3)
+    struct hostent_data buffer;
+#else
+    char buffer[1024];
+#endif
+    int err;
+    he = wxGethostbyname_r(hostname, &h, (void*)&buffer, sizeof(buffer), &err);
+    if (he == NULL)
     {
       /* Reset to invalid address */
       addr->s_addr = INADDR_NONE;
@@ -1822,11 +2002,14 @@ GSocketError GAddress_INET_SetPortName(GAddress *address, const char *port,
     return GSOCK_INVPORT;
   }
 
-#if defined(__WXPM__) && defined(__EMX__)
-  se = getservbyname(port, (char*)protocol);
+#if defined(HAVE_FUNC_GETSERVBYNAME_R_4)
+    struct servent_data buffer;
 #else
-  se = getservbyname(port, protocol);
+  char buffer[1024];
 #endif
+  struct servent serv;
+  se = wxGetservbyname_r(port, protocol, &serv,
+                        (void*)&buffer, sizeof(buffer));
   if (!se)
   {
     /* the cast to int suppresses compiler warnings about subscript having the
@@ -1876,7 +2059,15 @@ GSocketError GAddress_INET_GetHostName(GAddress *address, char *hostname, size_t
   addr = (struct sockaddr_in *)address->m_addr;
   addr_buf = (char *)&(addr->sin_addr);
 
-  he = gethostbyaddr(addr_buf, sizeof(addr->sin_addr), AF_INET);
+  struct hostent temphost;
+#if defined(HAVE_FUNC_GETHOSTBYNAME_R_3)
+  struct hostent_data buffer;
+#else
+  char buffer[1024];
+#endif
+  int err;
+  he = wxGethostbyaddr_r(addr_buf, sizeof(addr->sin_addr), AF_INET, &temphost,
+                        (void*)&buffer, sizeof(buffer), &err);
   if (he == NULL)
   {
     address->m_error = GSOCK_NOHOST;