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.