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.