Subject: Re: Leaked handles on Windows

Re: Leaked handles on Windows

From: Vlad Dinulescu <vlad.dinulescu_at_avira.com>
Date: Thu, 14 May 2009 12:04:57 +0300

    Fresh news from the battlefield: we've modified c-ares: removed
LoadLibrary calls, linked it with iphlapi.lib, and called
GetNetworkParams() directly.
    This time more handles show up up in Process Explorer, but the good
news is that further calls to ares_init do not leak more handles. Which
is great for applications that use lots of ares channels. I think this
approach is also faster, as it does not LoadLibrary() and FreeLibrary()
on every call to ares_init(). It does have the disadvantage that it
won't work on Windows 95, as the GetNetworkParams() function was first
introduced in Windows 98. Very small disadvantage in my opinion, and we
could work around that by using registry keys for nameserver
information, if we really wanted to keep supporting Windows 95.
     I'm attaching a small patch that illustrates the changes (you also
have to add iphlpapi.lib to the linker flags).

Best regards,
Vlad Dinulescu

Vlad Dinulescu wrote:
> Couldn't we stop loading dynamically iphlpapi.dll in c-ares, at runtime
> through LoadLibrary(), and just link c-ares against iphlpapi.dll?
>
> Yang Tse wrote:
>> 2009/5/13, Daniel Stenberg wrote:
>>
>>> (http://support.microsoft.com/default.aspx?scid=kb;en-us;836769)
>> Quoting the above link...
>>
>>> This problem may occur when the following conditions are both true:
>>>
>>> Your program uses LoadLibrary calls and FreeLibrary calls to load
>>> and to unload the Iphlpapi.dll file.
>>>
>>> A handle to the TCP/IP driver is not closed correctly when the
>>> Iphlpapi.dll file is unloaded.
>> I can make all sort of assumtions on what the second condition means,
>> but I really don't know what it actually means.
>>
>> Since the get_iphlpapi_dns_info() function does not open nor close
>> 'handles to the TCP/IP driver', whatever that means, in between the
>> calls to LoadLibrary and FreeLibrary. Why on earth does
>> GetNetworkParams() leak a handle?
>>
>> I fear the conditions mentioned above do not represent reality, and
>> actually a different set of conditions are the ones that apply.
>>
>> Ugh!
>>
>

--- ares_init.c Thu May 14 11:57:57 2009
+++ nou\ares_init.c Thu May 14 10:47:33 2009
@@ -497,8 +497,6 @@
   FIXED_INFO *fi = alloca (sizeof(*fi));
   DWORD size = sizeof (*fi);
   typedef DWORD (WINAPI* get_net_param_func) (FIXED_INFO*, DWORD*);
- get_net_param_func fpGetNetworkParams; /* available only on Win-98/2000+ */
- HMODULE handle;
   IP_ADDR_STRING *ipAddr;
   int i, count = 0;
   int debug = 0;
@@ -510,22 +508,10 @@
   if (!fi)
      return (0);
 
- handle = LoadLibrary ("iphlpapi.dll");
- if (!handle)
- return (0);
-
- fpGetNetworkParams = (get_net_param_func) GetProcAddress (handle, "GetNetworkParams");
- if (!fpGetNetworkParams)
- goto quit;
-
- res = (*fpGetNetworkParams) (fi, &size);
+ res = GetNetworkParams(fi,&size);
   if ((res != ERROR_BUFFER_OVERFLOW) && (res != ERROR_SUCCESS))
      goto quit;
 
- fi = alloca (size);
- if (!fi || (*fpGetNetworkParams) (fi, &size) != ERROR_SUCCESS)
- goto quit;
-
   if (debug)
   {
     printf ("Host Name: %s\n", fi->HostName);
@@ -556,9 +542,6 @@
   }
 
 quit:
- if (handle)
- FreeLibrary (handle);
-
   if (debug && left <= ip_size)
      printf ("Too many nameservers. Truncating to %d addressess", count);
   if (ret > ret_buf)
Received on 2009-05-14