1478 – Please use threadsafe functions in getHostByName

D issues are now tracked on GitHub. This Bugzilla instance remains as a read-only archive.
Issue 1478 - Please use threadsafe functions in getHostByName
Summary: Please use threadsafe functions in getHostByName
Status: RESOLVED FIXED
Alias: None
Product: D
Classification: Unclassified
Component: phobos (show other issues)
Version: D2
Hardware: x86 Linux
: P2 normal
Assignee: Walter Bright
URL:
Keywords: patch
Depends on:
Blocks:
Reported: 2007年09月06日 07:48 UTC by FeepingCreature
Modified: 2015年06月09日 01:31 UTC (History)
0 users

See Also:


Attachments
Add an attachment (proposed patch, testcase, etc.)

Note You need to log in before you can comment on or make changes to this issue.
Description FeepingCreature 2007年09月06日 07:48:03 UTC
The following patch will change socket.d to use threadsafe functions for the gethostbyname call on non-windows platforms. Not doing this can lead to all sorts of ugly problems when using sockets in multi-threaded programs.
The patch is originally for gdc's socket.d, but should be equally applicable to DMD.
diff socket.d.broken socket.d
487c487,497
< hostent* he = gethostbyname(toStringz(name));
---
> version (Windows)
> hostent* he = gethostbyname(toStringz(name));
> else
> {
> auto he = new hostent;
> auto buffer=new char[512];
> int errno;
> getHostByName_retry: // if we had extended do { } while { } this would not be necessary.
> auto res = gethostbyname_r(toStringz(name), he, buffer.ptr, buffer.length, &he, &errno);
> if (res == ERANGE) { buffer.length = buffer.length * 2; if (!he) he=new hostent; goto getHostByName_retry; }
> }
Comment 1 Brad Roberts 2007年10月13日 20:06:21 UTC
Given that the _r versions of the functions are glibc specific, I'm much more inclined to synchronize the call.
Additonally, this only protects one of the several non-threadsafe networking info api's.
Comitted this diff:
$ svn diff std/socket.d 
Index: std/socket.d
===================================================================
--- std/socket.d (revision 358)
+++ std/socket.d (working copy)
@@ -453,7 +453,8 @@
 */ 
 bool getHostByName(string name)
 {
- hostent* he = gethostbyname(toStringz(name));
+ hostent* he;
+ synchronized he = gethostbyname(toStringz(name));
 if(!he)
 return false;
 validHostent(he);
@@ -468,7 +469,8 @@
 bool getHostByAddr(uint addr)
 {
 uint x = htonl(addr);
- hostent* he = gethostbyaddr(&x, 4, cast(int)AddressFamily.INET);
+ hostent* he;
+ synchronized he = gethostbyaddr(&x, 4, cast(int)AddressFamily.INET);
 if(!he)
 return false;
 validHostent(he);
@@ -485,7 +487,8 @@
 bool getHostByAddr(string addr)
 {
 uint x = inet_addr(std.string.toStringz(addr));
- hostent* he = gethostbyaddr(&x, 4, cast(int)AddressFamily.INET);
+ hostent* he;
+ synchronized he = gethostbyaddr(&x, 4, cast(int)AddressFamily.INET);
 if(!he)
 return false;
 validHostent(he);
Comment 2 Brad Roberts 2007年10月14日 16:40:02 UTC
downs: I saw your comments in scrollback on irc. Two comments:
1) thanks.. you're right about the need to globally synchronize and not per-class-instance synchronize. I've fixed that:
- synchronized he = gethostbyname(toStringz(name));
+ synchronized(this.classinfo) he = gethostbyname(toStringz(name));
2) Regarding the use of static if, that would only work if there was sufficient configury mechanics to make sure that the _r versions were only included if they exist. All static if can see is what's been declared, not what actually is linkable. My main objection isn't really the declaration part of _r, but the very wierd usage of needing to grow that buffer and iterate many times. That'd likely end up more expensive than just synching.
Thanks for catching #1.
Later,
Brad
Comment 3 FeepingCreature 2007年10月15日 03:32:02 UTC
d-bugmail@puremagic.com wrote:
> http://d.puremagic.com/issues/show_bug.cgi?id=1478 
>
>
>
>
>
> ------- Comment #2 from braddr@puremagic.com 2007年10月14日 16:40 -------
> downs: I saw your comments in scrollback on irc. Two comments:
>
> 1) thanks.. you're right about the need to globally synchronize and not
> per-class-instance synchronize. I've fixed that:
>
> - synchronized he = gethostbyname(toStringz(name));
> + synchronized(this.classinfo) he = gethostbyname(toStringz(name));
>
> 2) Regarding the use of static if, that would only work if there was sufficient
> configury mechanics to make sure that the _r versions were only included if
> they exist. All static if can see is what's been declared, not what actually
> is linkable. My main objection isn't really the declaration part of _r, but
> the very wierd usage of needing to grow that buffer and iterate many times. 
> That'd likely end up more expensive than just synching.
>
> Thanks for catching #1.
>
> Later,
> Brad
>
>
> 
Regarding the growing part.
On my system, the provided default buffer is sufficient, so it'd never
need to regrow it. That's actually only there in case the buffer turns
out to be insufficient on some systems.
Here's an alternative. Since the required buffer size is unlikely to
change much on the same system, how about storing the largest needed
buffer size in a static class variable and update it on resize? This
way, the resize would only take place the first time that the buffer is
too small.
Regarding the function being available on systems that don't actually
have it; isn't that a bug in itself? Not sure on this one.
Thanks for your reply though.
 --downs / feep
	
		
___________________________________________________________ 
Der fr
Comment 4 Walter Bright 2007年11月03日 21:46:39 UTC
Fixed dmd 1.023


AltStyle によって変換されたページ (->オリジナル) /