[ https://issues.apache.org/jira/browse/ZOOKEEPER-208?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]
Chris Darroch updated ZOOKEEPER-208: ------------------------------------ Attachment: zookeeper-strtok_getaddrinfo-trunk.patch I've reformatted the original submitter's normal patch as a unified diff file to use against 3.0.0 and SVN trunk (at the moment). I won't grant a license for it, though, since I didn't do the original work. Hopefully this saves the submitter a little work. If they can just sign off on this file, they shouldn't need to deal with any other details. > 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 > Assignee: Austin Shoemaker > Priority: Critical > Fix For: 3.1.0 > > Attachments: zookeeper-strtok_getaddrinfo-trunk.patch > > > 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.