Zookeeper C client uses API that are not thread safe, causing crashes when 
multiple instances are active
--------------------------------------------------------------------------------------------------------

                 Key: ZOOKEEPER-208
                 URL: https://issues.apache.org/jira/browse/ZOOKEEPER-208
             Project: Zookeeper
          Issue Type: Bug
          Components: c client
    Affects Versions: 3.0.0
         Environment: Linux
            Reporter: Austin Shoemaker
            Priority: Critical


The Zookeeper C client library uses gethostbyname and strtok, both of which are 
not safe to use from multiple threads. Below is the original patch we made 
which fixes the problem.

The problem is resolved by using getaddrinfo and strtok_r in place of the older 
API.

Patch for zookeeper-c-client-2.2.1/src/zookeeper.c (2008-06-09 on SF.net)

241c241
<     struct hostent *he;
---
>       struct addrinfo hints, *res, *res0;
243,245d242
<     struct sockaddr_in *addr4;
<     struct sockaddr_in6 *addr6;
<     char **ptr;
247a245
>       char *strtok_last;
263c261
<     host=strtok(hosts, ",");
---
>     host=strtok_r(hosts, ",", &strtok_last);
283,294c281,297
<         he = gethostbyname(host);
<         if (!he) {
<             LOG_ERROR(("could not resolve %s", host));
<             errno=EINVAL;
<             rc=ZBADARGUMENTS;
<             goto fail;
<         }
<
<         /* Setup the address array */
<         for(ptr = he->h_addr_list;*ptr != 0; ptr++) {
<             if (zh->addrs_count == alen) {
<                 void *tmpaddr;
---
>               
>               memset(&hints, 0, sizeof(hints));
>               hints.ai_flags = AI_ADDRCONFIG;
>               hints.ai_family = AF_UNSPEC;
>               hints.ai_socktype = SOCK_STREAM;
>               hints.ai_protocol = IPPROTO_TCP;
>
>               if (getaddrinfo(host, port_spec, &hints, &res0) != 0) {
>                       LOG_ERROR(("getaddrinfo: %s\n", strerror(errno)));
>                       rc=ZSYSTEMERROR;
>                       goto fail;
>               }
>               
>               for (res = res0; res; res = res->ai_next) {
>                       // Expand address list if needed
>                       if (zh->addrs_count == alen) {
>                               void *tmpaddr;
304,313c307,312
<             }
<             addr = &zh->addrs[zh->addrs_count];
<             addr4 = (struct sockaddr_in*)addr;
<             addr6 = (struct sockaddr_in6*)addr;
<             addr->sa_family = he->h_addrtype;
<             if (addr->sa_family == AF_INET) {
<                 addr4->sin_port = htons(port);
<                 memset(&addr4->sin_zero, 0, sizeof(addr4->sin_zero));
<                 memcpy(&addr4->sin_addr, *ptr, he->h_length);
<                 zh->addrs_count++;
---
>                       }
>                       
>                       // Copy addrinfo into address list
>                       addr = &zh->addrs[zh->addrs_count];
>                       switch (res->ai_family) {
>                       case AF_INET:
315,320c314
<             } else if (addr->sa_family == AF_INET6) {
<                 addr6->sin6_port = htons(port);
<                 addr6->sin6_scope_id = 0;
<                 addr6->sin6_flowinfo = 0;
<                 memcpy(&addr6->sin6_addr, *ptr, he->h_length);
<                 zh->addrs_count++;
---
>                       case AF_INET6:
322,327c316,328
<             } else {
<                 LOG_WARN(("skipping unknown address family %x for %s",
<                         addr->sa_family, zh->hostname));
<             }
<         }
<         host = strtok(0, ",");
---
>                               memcpy(addr, res->ai_addr, res->ai_addrlen);
>                               ++zh->addrs_count;
>                               break;
>                       default:
>                               LOG_WARN(("skipping unknown address family %x 
> for %s",
>                                       res->ai_family, zh->hostname));
>                               break;
>                       }
>               }
>               
>               freeaddrinfo(res0);
>
>               host = strtok_r(0, ",", &strtok_last);
329a331
>


-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.

Reply via email to