* autoload.cc: Use LoadDLLfuncEx3 for all winmm functions. Accommodate changes

to LoadDLLprime.
(LoadDLLprime): Take an extra argument indicating whether this dll needs
special handling on fork.  Place this information in the "handle" location.
(LoadDLLfuncEx3): Eliminate "func" handling.  Pass new no_resolve_on_fork
argument to LoadDLLprime.
(dll_load): New function.
(std_dll_init): Accommodate changes to dll_info::handle.  Use dll_load to load
DLL in both cases where it is used.
This commit is contained in:
Christopher Faylor 2011-02-26 23:30:33 +00:00
parent e80f6dc8f0
commit a16b0549d4
2 changed files with 65 additions and 38 deletions

View File

@ -1,3 +1,16 @@
2011-02-26 Christopher Faylor <me+cygwin@cgf.cx>
* autoload.cc: Use LoadDLLfuncEx3 for all winmm functions. Accommodate
changes to LoadDLLprime.
(LoadDLLprime): Take an extra argument indicating whether this dll
needs special handling on fork. Place this information in the "handle"
location.
(LoadDLLfuncEx3): Eliminate "func" handling. Pass new
no_resolve_on_fork argument to LoadDLLprime.
(dll_load): New function.
(std_dll_init): Accommodate changes to dll_info::handle. Use dll_load
to load DLL in both cases where it is used.
2011-02-26 Corinna Vinschen <corinna@vinschen.de>
* autoload.cc: Make autoloaded ntdll function non-optional. Ditto for

View File

@ -60,13 +60,13 @@ bool NO_COPY wsock_started;
/* LoadDLLprime is used to prime the DLL info information, providing an
additional initialization routine to call prior to calling the first
function. */
#define LoadDLLprime(dllname, init_also) __asm__ (" \n\
#define LoadDLLprime(dllname, init_also, no_resolve_on_fork) __asm__ (" \n\
.ifndef " #dllname "_primed \n\
.section .data_cygwin_nocopy,\"w\" \n\
.align 4 \n\
."#dllname "_info: \n\
.long _std_dll_init \n\
.long 0 \n\
.long " #no_resolve_on_fork " \n\
.long -1 \n\
.long " #init_also " \n\
.string16 \"" #dllname ".dll\" \n\
@ -88,8 +88,8 @@ bool NO_COPY wsock_started;
LoadDLLfuncEx3(name, n, dllname, notimp, err, 0)
/* Main DLL setup stuff. */
#define LoadDLLfuncEx3(name, n, dllname, notimp, err, fn) \
LoadDLLprime (dllname, dll_func_load) \
#define LoadDLLfuncEx3(name, n, dllname, notimp, err, no_resolve_on_fork) \
LoadDLLprime (dllname, dll_func_load, no_resolve_on_fork) \
__asm__ (" \n\
.section ." #dllname "_autoload_text,\"wx\" \n\
.global _" mangle (name, n) " \n\
@ -102,7 +102,7 @@ _win32_" mangle (name, n) ": \n\
1:movl (2f),%eax \n\
call *(%eax) \n\
2:.long ." #dllname "_info \n\
.long (" #n "+" #notimp ") | (((" #err ") & 0xff) <<16) | (((" #fn ") & 0xff) << 24) \n\
.long (" #n "+" #notimp ") | (((" #err ") & 0xff) <<16) \n\
.asciz \"" #name "\" \n\
.text \n\
");
@ -204,6 +204,21 @@ union retchain
long long ll;
};
/* This function is a workaround for the problem reported here:
http://cygwin.com/ml/cygwin/2011-02/msg00552.html
and discussed here:
http://cygwin.com/ml/cygwin-developers/2011-02/threads.html#00007
To wit: winmm.dll calls FreeLibrary in its DllMain and that can result
in LoadLibraryExW returning an ERROR_INVALID_ADDRESS. */
static bool
dll_load (HANDLE& handle, WCHAR *name)
{
HANDLE h = LoadLibraryExW (name, NULL, (in_forkee && handle) ? DONT_RESOLVE_DLL_REFERENCES : 0);
return h ? (handle = h) : 0;
}
#define RETRY_COUNT 10
/* The standard DLL initialization routine. */
@ -221,21 +236,22 @@ std_dll_init ()
yield ();
}
while (InterlockedIncrement (&dll->here));
else if (!dll->handle)
else if ((uintptr_t) dll->handle <= 1)
{
fenv_t fpuenv;
fegetenv (&fpuenv);
WCHAR dll_path[MAX_PATH];
DWORD err = ERROR_SUCCESS;
int i;
/* http://www.microsoft.com/technet/security/advisory/2269637.mspx */
wcpcpy (wcpcpy (dll_path, windows_system_directory), dll->name);
/* MSDN seems to imply that LoadLibrary can fail mysteriously, so,
since there have been reports of this in the mailing list, retry
several times before giving up. */
for (int i = 1; i <= RETRY_COUNT; i++)
for (i = 1; i <= RETRY_COUNT; i++)
{
/* If loading the library succeeds, just leave the loop. */
if ((dll->handle = LoadLibraryW (dll_path)) != NULL)
if (!dll_load (dll->handle, dll_path))
break;
/* Otherwise check error code returned by LoadLibrary. If the
error code is neither NOACCESS nor DLL_INIT_FAILED, break out
@ -246,15 +262,13 @@ std_dll_init ()
if (i < RETRY_COUNT)
yield ();
}
if (!dll->handle)
if ((uintptr_t) dll->handle <= 1)
{
/* If LoadLibrary with full path returns one of the weird errors
reported on the Cygwin mailing list, retry with only the DLL
name. Checking the error codes allows to restrict loading
with just the DLL name to this specific problem. */
if ((err == ERROR_NOACCESS || err == ERROR_DLL_INIT_FAILED)
&& (dll->handle = LoadLibraryW (dll->name)) != NULL)
;
name. Only do this when the above retry loop has been exhausted. */
if (i > RETRY_COUNT && dll_load (dll->handle, dll->name))
/* got it with the fallback */;
else if ((func->decoration & 1))
dll->handle = INVALID_HANDLE_VALUE;
else
@ -330,7 +344,7 @@ wsock_init ()
return ret.ll;
}
LoadDLLprime (ws2_32, _wsock_init)
LoadDLLprime (ws2_32, _wsock_init, 0)
LoadDLLfuncEx2 (DnsQuery_A, 24, dnsapi, 1, 127) // ERROR_PROC_NOT_FOUND
LoadDLLfuncEx (DnsRecordListFree, 8, dnsapi, 1)
@ -435,27 +449,27 @@ LoadDLLfunc (SetProcessWindowStation, 4, user32)
LoadDLLfunc (SetThreadDesktop, 4, user32)
LoadDLLfunc (ShowWindowAsync, 8, user32)
LoadDLLfunc (timeBeginPeriod, 4, winmm)
LoadDLLfunc (timeEndPeriod, 4, winmm)
LoadDLLfunc (timeGetDevCaps, 8, winmm)
LoadDLLfunc (timeGetTime, 0, winmm)
LoadDLLfunc (waveInAddBuffer, 12, winmm)
LoadDLLfunc (waveInClose, 4, winmm)
LoadDLLfunc (waveInGetNumDevs, 0, winmm)
LoadDLLfunc (waveInOpen, 24, winmm)
LoadDLLfunc (waveInPrepareHeader, 12, winmm)
LoadDLLfunc (waveInReset, 4, winmm)
LoadDLLfunc (waveInStart, 4, winmm)
LoadDLLfunc (waveInUnprepareHeader, 12, winmm)
LoadDLLfunc (waveOutClose, 4, winmm)
LoadDLLfunc (waveOutGetNumDevs, 0, winmm)
LoadDLLfunc (waveOutGetVolume, 8, winmm)
LoadDLLfunc (waveOutOpen, 24, winmm)
LoadDLLfunc (waveOutPrepareHeader, 12, winmm)
LoadDLLfunc (waveOutReset, 4, winmm)
LoadDLLfunc (waveOutSetVolume, 8, winmm)
LoadDLLfunc (waveOutUnprepareHeader, 12, winmm)
LoadDLLfunc (waveOutWrite, 12, winmm)
LoadDLLfuncEx3 (timeBeginPeriod, 4, winmm, 0, 0, 1)
LoadDLLfuncEx3 (timeEndPeriod, 4, winmm, 0, 0, 1)
LoadDLLfuncEx3 (timeGetDevCaps, 8, winmm, 0, 0, 1)
LoadDLLfuncEx3 (timeGetTime, 0, winmm, 0, 0, 1)
LoadDLLfuncEx3 (waveInAddBuffer, 12, winmm, 0, 0, 1)
LoadDLLfuncEx3 (waveInClose, 4, winmm, 0, 0, 1)
LoadDLLfuncEx3 (waveInGetNumDevs, 0, winmm, 0, 0, 1)
LoadDLLfuncEx3 (waveInOpen, 24, winmm, 0, 0, 1)
LoadDLLfuncEx3 (waveInPrepareHeader, 12, winmm, 0, 0, 1)
LoadDLLfuncEx3 (waveInReset, 4, winmm, 0, 0, 1)
LoadDLLfuncEx3 (waveInStart, 4, winmm, 0, 0, 1)
LoadDLLfuncEx3 (waveInUnprepareHeader, 12, winmm, 0, 0, 1)
LoadDLLfuncEx3 (waveOutClose, 4, winmm, 0, 0, 1)
LoadDLLfuncEx3 (waveOutGetNumDevs, 0, winmm, 0, 0, 1)
LoadDLLfuncEx3 (waveOutGetVolume, 8, winmm, 0, 0, 1)
LoadDLLfuncEx3 (waveOutOpen, 24, winmm, 0, 0, 1)
LoadDLLfuncEx3 (waveOutPrepareHeader, 12, winmm, 0, 0, 1)
LoadDLLfuncEx3 (waveOutReset, 4, winmm, 0, 0, 1)
LoadDLLfuncEx3 (waveOutSetVolume, 8, winmm, 0, 0, 1)
LoadDLLfuncEx3 (waveOutUnprepareHeader, 12, winmm, 0, 0, 1)
LoadDLLfuncEx3 (waveOutWrite, 12, winmm, 0, 0, 1)
LoadDLLfunc (accept, 12, ws2_32)
LoadDLLfunc (bind, 12, ws2_32)