This is the mail archive of the cygwin-developers mailing list for the Cygwin project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: LoadLibrary error 487 (was Re: Please test latest developer snapshot)


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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]