@@ -314,7 +314,8 @@ dll_list::alloc (HINSTANCE h, per_process *p, dll_type type)
314314 /* Already loaded? For linked DLLs, only compare the basenames. Linked
315315 DLLs are loaded using just the basename and the default DLL search path.
316316 The Windows loader picks up the first one it finds.
317- This also applies to cygwin1.dll and the main-executable (DLL_SELF).
317+ This also applies to cygwin1.dll and the main-executable (DLL_SELF)
318+ and native DLLs (DLL_NATIVE).
318319 When in_load_after_fork, dynamically loaded dll's are reloaded
319320 using their parent's forkable_ntname, if available. */
320321 dll *d = (type != DLL_LOAD) ? dlls.find_by_modname (modname) :
@@ -346,7 +347,6 @@ dll_list::alloc (HINSTANCE h, per_process *p, dll_type type)
346347 {
347348 size_t forkntsize = forkable_ntnamesize (type, ntname, modname);
348349
349- /* FIXME: Change this to new at some point. */
350350 d = (dll *) cmalloc (HEAP_2_DLL, sizeof (*d)
351351 + ((ntnamelen + forkntsize) * sizeof (*ntname)));
352352
@@ -356,14 +356,20 @@ dll_list::alloc (HINSTANCE h, per_process *p, dll_type type)
356356 d->modname = d->ntname + (modname - ntname);
357357 d->handle = h;
358358 d->count = 0 ; /* Reference counting performed in dlopen/dlclose. */
359- /* DLL_SELF dtors (main-executable, cygwin1.dll) are run elsewhere */
360- d->has_dtors = type != DLL_SELF;
359+ /* DLL_SELF dtors (main-executable, cygwin1.dll) are run elsewhere,
360+ DLL_NATIVE dtors whereever native DLLs do it. */
361+ d->has_dtors = (type == DLL_LINK || type == DLL_LOAD);
361362 d->p = p;
362363 d->ndeps = 0 ;
363364 d->deps = NULL ;
364365 d->image_size = ((pefile*)h)->optional_hdr ()->SizeOfImage ;
365366 d->preferred_base = (void *) ((pefile*)h)->optional_hdr ()->ImageBase ;
366367 d->type = type;
368+ if (type == DLL_NATIVE)
369+ {
370+ d->count = 1 ;
371+ reload_on_fork = 1 ;
372+ }
367373 d->fii .IndexNumber .QuadPart = -1LL ;
368374 if (!forkntsize)
369375 d->forkable_ntname = NULL ;
@@ -541,8 +547,10 @@ dll_list::topsort_visit (dll* d, bool seek_tail)
541547}
542548
543549
550+ /* If called from dlopen/dlclose, from_dlfcn is true and we return any dll if
551+ the address matches. Otherwise we only want DLL_LINK and DLL_LOAD dlls. */
544552dll *
545- dll_list::find (void *retaddr, bool find_self )
553+ dll_list::find (void *retaddr, bool from_dlfcn )
546554{
547555 MEMORY_BASIC_INFORMATION m;
548556 if (!VirtualQuery (retaddr, &m, sizeof m))
@@ -551,7 +559,8 @@ dll_list::find (void *retaddr, bool find_self)
551559
552560 dll *d = &start;
553561 while ((d = d->next ))
554- if ((d->type != DLL_SELF || find_self) && d->handle == h)
562+ if ((from_dlfcn || d->type == DLL_LINK || d->type == DLL_LOAD)
563+ && d->handle == h)
555564 break ;
556565 return d;
557566}
@@ -569,12 +578,16 @@ dll_list::detach (void *retaddr)
569578 guard (true );
570579 if ((d = find (retaddr)))
571580 {
572- /* Ensure our exception handler is enabled for destructors */
573- exception protect;
574- /* Call finalize function if we are not already exiting */
575- if (!exit_state)
576- __cxa_finalize (d->handle );
577- d->run_dtors ();
581+ /* Only run dtors for Cygwin DLLs. */
582+ if (d->type == DLL_LINK || d->type == DLL_LOAD)
583+ {
584+ /* Ensure our exception handler is enabled for destructors */
585+ exception protect;
586+ /* Call finalize function if we are not already exiting */
587+ if (!exit_state)
588+ __cxa_finalize (d->handle );
589+ d->run_dtors ();
590+ }
578591 d->prev ->next = d->next ;
579592 if (d->next )
580593 d->next ->prev = d->prev ;
@@ -596,8 +609,9 @@ dll_list::init ()
596609 /* Walk the dll chain, initializing each dll */
597610 dll *d = &start;
598611 dll_global_dtors_recorded = d->next != NULL ;
612+ /* Init linked and early loaded Cygwin DLLs. */
599613 while ((d = d->next ))
600- if (d->type != DLL_SELF) /* linked and early loaded dlls */
614+ if (d->type == DLL_LINK || d-> type == DLL_LOAD)
601615 d->init ();
602616}
603617
@@ -684,7 +698,10 @@ dll_list::load_after_fork (HANDLE parent)
684698
685699 in_load_after_fork = true ;
686700 if (reload_on_fork)
687- load_after_fork_impl (parent, dlls.istart (DLL_LOAD), 0 );
701+ {
702+ load_after_fork_impl (parent, dlls.istart (DLL_NATIVE), 0 );
703+ load_after_fork_impl (parent, dlls.istart (DLL_LOAD), 0 );
704+ }
688705 track_self ();
689706 in_load_after_fork = false ;
690707}
@@ -709,7 +726,7 @@ void dll_list::load_after_fork_impl (HANDLE parent, dll* d, int retries)
709726 the LoadLibraryExW call unconditional.
710727 */
711728 for ( ; d; d = dlls.inext ())
712- if (d->handle != d->preferred_base )
729+ if (hold_type == DLL_LOAD && d->handle != d->preferred_base )
713730 {
714731 /* See if the DLL will load in proper place. If not, unload it,
715732 reserve the memory around it, and try again.
@@ -757,9 +774,11 @@ void dll_list::load_after_fork_impl (HANDLE parent, dll* d, int retries)
757774 interim mapping (for rebased dlls) . The dll list is sorted in
758775 dependency order, so we shouldn't pull in any additional dlls
759776 outside our control. */
760- for (dll *d = dlls.istart (DLL_LOAD ); d; d = dlls.inext ())
777+ for (dll *d = dlls.istart (hold_type ); d; d = dlls.inext ())
761778 {
762- if (d->handle == d->preferred_base )
779+ if (hold_type == DLL_NATIVE)
780+ /* just LoadLibrary... */ ;
781+ else if (d->handle == d->preferred_base )
763782 {
764783 if (!VirtualFree (d->handle , 0 , MEM_RELEASE))
765784 fabort (" unable to release protective reservation for %W (%p), %E" ,
0 commit comments