This is the mail archive of the
cygwin-developers
mailing list for the Cygwin project.
Re: LoadLibrary error 487 (was Re: Please test latest developer snapshot)
- From: Christopher Faylor <cgf-use-the-mailinglist-please at cygwin dot com>
- To: cygwin-developers at cygwin dot com
- Date: Sat, 26 Feb 2011 13:14:33 -0500
- Subject: Re: LoadLibrary error 487 (was Re: Please test latest developer snapshot)
- References: <20110217120400.GB29762@calimero.vinschen.de> <4D683A37.5060408@acm.org> <4D6844C8.7010801@acm.org> <20110226103549.GB9392@calimero.vinschen.de> <20110226153246.GC9392@calimero.vinschen.de> <20110226180427.GF9392@calimero.vinschen.de>
- Reply-to: cygwin-developers at cygwin dot com
On Sat, Feb 26, 2011 at 07:04:27PM +0100, Corinna Vinschen wrote:
>On Feb 26 16:32, Corinna Vinschen wrote:
>> I'm seriously puzzled. Any input would be much appreciated.
>>
>> On Feb 26 11:35, Corinna Vinschen wrote:
>> > On Feb 25 16:09, David Rothenberger wrote:
>> > > I was able to reproduce this using a clone of the git repository itself:
>> > >
>> > > % uname -a
>> > > CYGWIN_NT-5.1 tela 1.7.8s(0.236/5/3) 20110221 20:36:00 i686 Cygwin
>> > > % git clone git://github.com/git/git.git
>> > > Cloning into git...
>> > > remote: Counting objects: 134689, done.
>> > > remote: Compressing objects: 100% (39672/39672), done.
>> > > remote: Total 134689 (delta 100250), reused 126970 (delta 93150)
>> > > Receiving objects: 100% (134689/134689), 28.44 MiB | 621 KiB/s, done.
>> > > Resolving deltas: 100% (100250/100250), done.
>> > > % cd git/
>> > > % git log
>> > > 0 [main] git 3088 C:\cygwin\bin\git.exe: *** fatal error - could not load C:\WINDOWS\system32\winmm.dll, Win32 error 487
>> >
>> > Thanks for the report. I can reproduce this under Windows XP but
>> > not under Windows 7. Stay tuned.
>> [...]
>> The only workaround which works for me is to use the GetTickCount()
>> function instead of the timeGetTime() function in hires_ms::nsecs():
>> [...]
>> Does anybody have an idea what could cause this problem? I already
>> googled for this but all I can come up with is questions with no reply
>> or questions which refer to loading a DLL as data or resource. And
>> the replies aren't very helpful either.
>
>A couple of minutes ago I found this:
>
>http://www.tech-archive.net/Archive/DotNet/microsoft.public.dotnet.framework.clr/2007-02/msg00000.html
>
>While this is about static loading, the MSFT guy claims that winmm calls
>FreeLibrary in DllMain(). His workaround to use LoadLibrary works for
>the guy which has this problem.
>
>This gave me a crazy idea. The problem doesn't occur in the git called
>from the command line, but in a forked child. And then, if winmm calls
>FreeLibrary in DllMain (at least on XP), maybe that's our problem here,
>too. Fortunately there's the LoadLibraryEx function, which accepts the
>parameter DONT_RESOLVE_DLL_REFERENCES, which in turn allows to get a
>module handle without calling DllMain. So I did this:
>
>Index: autoload.cc
>===================================================================
>RCS file: /cvs/src/src/winsup/cygwin/autoload.cc,v
>retrieving revision 1.183
>diff -u -p -r1.183 autoload.cc
>--- autoload.cc 15 Feb 2011 15:56:00 -0000 1.183
>+++ autoload.cc 26 Feb 2011 17:52:06 -0000
>@@ -241,6 +241,14 @@ std_dll_init ()
> error code is neither NOACCESS nor DLL_INIT_FAILED, break out
> of the loop. */
> err = GetLastError ();
>+ if (err == ERROR_INVALID_ADDRESS)
>+ {
>+ if ((dll->handle = LoadLibraryExW (dll_path, 0,
>+ DONT_RESOLVE_DLL_REFERENCES))
>+ != NULL)
>+ break;
>+ err = GetLastError ();
>+ }
> if (err != ERROR_NOACCESS && err != ERROR_DLL_INIT_FAILED)
> break;
> if (i < RETRY_COUNT)
>
>In theory, that should be seriously broken. However, it actually works.
>This LoadLibraryEx call returns a module handle, and the subsequently
>fetched function pointer to timeGetTime() is really valid and returns
>the expected values on XP!
>
>I don't understand that. It shouldn't work. But it does.
>
>Chris, what do you think? Is that something we should try? Maybe we
>should try this only if we set a flag in some not yet existing
>LoadDLLfuncEx4?
I think I'd be ok with the change if you made that:
if (err == ERROR_INVALID_ADDRESS && in_forkee)
It's still not foolproof but at least we wouldn't be affecting non-forked
processes and, in theory, the data segments of loaded dlls would be properly
filled out in a fork().
In fact, hmm. I wonder if you could just change std_dll_init so that it
always used DONT_RESOLVE_DLL_REFERENCES when in_forkee. That might speed
fork up a little.
This also assumes that Cygwin got in first to load the dll and that it's
being loaded during fork startup but I think that is a given, right?
(Of course Microsoft says not to use this flag so I wonder if it will be
gone or broken in Windows 8)
cgf