* net.cc (call_gaa): New thread function to call GetAdaptersAddresses.

(get_adapters_addresses): Call call_gaa.  If necessary, call it as
	child thread.  Explain why that's necessary.
This commit is contained in:
Corinna Vinschen 2012-03-08 16:02:44 +00:00
parent efb1f061f1
commit 3e25449aa5
2 changed files with 56 additions and 15 deletions

View File

@ -1,3 +1,9 @@
2012-03-08 Václav Zeman <vhaisman@gmail.com>
* net.cc (call_gaa): New thread function to call GetAdaptersAddresses.
(get_adapters_addresses): Call call_gaa. If necessary, call it as
child thread. Explain why that's necessary.
2012-03-08 Václav Zeman <vhaisman@gmail.com> 2012-03-08 Václav Zeman <vhaisman@gmail.com>
* path.cc (readlink): Avoid calling strlen() twice. * path.cc (readlink): Avoid calling strlen() twice.

View File

@ -1650,36 +1650,71 @@ ip_addr_prefix (PIP_ADAPTER_UNICAST_ADDRESS pua, PIP_ADAPTER_PREFIX pap)
#define GAA_FLAG_INCLUDE_ALL_INTERFACES 0x0100 #define GAA_FLAG_INCLUDE_ALL_INTERFACES 0x0100
#endif #endif
bool struct gaa_wa {
get_adapters_addresses (PIP_ADAPTER_ADDRESSES *pa_ret, ULONG family) ULONG family;
PIP_ADAPTER_ADDRESSES *pa_ret;
};
DWORD WINAPI
call_gaa (LPVOID param)
{ {
DWORD ret, size = 0; DWORD ret, size = 0;
gaa_wa *p = (gaa_wa *) param;
PIP_ADAPTER_ADDRESSES pa0 = NULL; PIP_ADAPTER_ADDRESSES pa0 = NULL;
if (!pa_ret) if (!p->pa_ret)
return ERROR_BUFFER_OVERFLOW return GetAdaptersAddresses (p->family, GAA_FLAG_INCLUDE_PREFIX
== GetAdaptersAddresses (family, GAA_FLAG_INCLUDE_PREFIX
| GAA_FLAG_INCLUDE_ALL_INTERFACES, | GAA_FLAG_INCLUDE_ALL_INTERFACES,
NULL, NULL, &size); NULL, NULL, &size);
do do
{ {
ret = GetAdaptersAddresses (family, GAA_FLAG_INCLUDE_PREFIX ret = GetAdaptersAddresses (p->family, GAA_FLAG_INCLUDE_PREFIX
| GAA_FLAG_INCLUDE_ALL_INTERFACES, | GAA_FLAG_INCLUDE_ALL_INTERFACES,
NULL, pa0, &size); NULL, pa0, &size);
if (ret == ERROR_BUFFER_OVERFLOW if (ret == ERROR_BUFFER_OVERFLOW
&& !(pa0 = (PIP_ADAPTER_ADDRESSES) realloc (pa0, size))) && !(pa0 = (PIP_ADAPTER_ADDRESSES) realloc (pa0, size)))
break; break;
} }
while (ret == ERROR_BUFFER_OVERFLOW); while (ret == ERROR_BUFFER_OVERFLOW);
if (ret != ERROR_SUCCESS) if (pa0)
{ {
if (pa0) if (ret != ERROR_SUCCESS)
free (pa0); {
*pa_ret = NULL; free (pa0);
return false; *p->pa_ret = pa0;
}
else
*p->pa_ret = pa0;
} }
*pa_ret = pa0; return ret;
return true; }
bool
get_adapters_addresses (PIP_ADAPTER_ADDRESSES *pa_ret, ULONG family)
{
DWORD ret;
gaa_wa param = { family, pa_ret ?: NULL };
if ((uintptr_t) &param >= (uintptr_t) 0x80000000L)
{
/* Starting with Windows Vista, GetAdaptersAddresses fails with error 998,
if it's running in a thread with a stack located in the large address
area. So, if we're running in a pthread with such a stack, we call
GetAdaptersAddresses in a child thread with an OS-allocated stack,
which is guaranteed to be located in the lower address area. */
HANDLE thr = CreateThread (NULL, 0, call_gaa, &param, 0, NULL);
if (!thr)
{
debug_printf ("CreateThread: %E");
return false;
}
WaitForSingleObject (thr, INFINITE);
GetExitCodeThread (thr, &ret);
CloseHandle (thr);
}
else
ret = call_gaa (&param);
return ret == ERROR_SUCCESS || (!pa_ret && ret == ERROR_BUFFER_OVERFLOW);
} }
#define WS_IFF_UP 1 #define WS_IFF_UP 1