TIP: Click on subject to list as thread! ANSI
echo: os2prog
to: Denis Tonn
from: Jonathan de Boyne Pollard
date: 1998-09-27 15:57:32
subject: How do DLLs load and unload ?

DT> If you are asking about the sequence that each DLL's InitTerm are 
 DT> called during process end, I would have to check into it. 

No.  I'm asking how OS/2 resolves the chicken-and-egg problem outlined in
my original message (not being able to unmap the modules until the InitTerm
has been called, but not being able to determine what InitTerms to call
until it has traversed the module graph and unmapped the modules whose
reference counts have dropped to zero).  As far as I could see, the only
way to resolve this dilemma is to have the kernel call into user-mode code
*while* it is traversing the module graph and altering the reference
counts, which I think is *very* ugly.  Your message confirmed this:

 DT> Yep, it calls ring 3 from ring 0, and sets up a return address on the
 DT> stack that points into DOSCALL1. The code in DOSCALL1 then gets back 
 DT> to ring 0 through a callgate (actually, the stack setup is done in
 DT> DOSCALL1). Simple stack manipulation ..   

The problem with this is with recursion, and pathological InitTerm
functions.  As I said:

 JP>> [...] the pathological, but permissible, case that the InitTerm
 JP>> function of a module may itself call DosLoadModule or 
 JP>> DosFreeModule ?  Or the equally pathological case that the InitTerm
 JP>> function, either accidentally or deliberately, never returns at
 JP>> all (leaving the kernel internals in an intermediate state) [...]

I wasn't asking whether this sort of code was *valid*, by the way.  It's
obviously valid, and in any case a decent operating system has to protect
itself against mischeivous application code.  The question is how does the
kernel deal with the kernel stack overflow or deadlock issues that result ?
 You didn't see that this was the main thrust of my question, and only
referred to this obliquely:

 DT> It's possible to create a loop here during cleanup. I don't know 
 DT> if there are any checks to prevent this. 

*That's* the issue.  Obviously calls to DosLoadModule and DosFreeModule
must be serialised.  This in turn implies that the thread that is making
the call must lock the module table.  But what if a call to DosFreeModule
occurs in the termination function of a DLL ?  Surely this causes a
deadlock ?  If it *doesn't* cause a deadlock (i.e. if the module table is
guarded by some sort of recursive mutex), then what happens if the InitTerm
code tries to do *really* pathological things, like DosFreeModule *itself*,
or attempt to DosLoadModule a module that references it and causes its
reference count to become *non*-zero ?  And how does the kernel handle
other pathological cases, such as when many modules have calls to
DosFreeModule in their termination code, resulting in significant nesting
on the kernel stack ?

Incidentally, what do you mean by :

 DT> (actually, the stack setup is done in DOSCALL1). 

Do you mean that the user-mode stub in DOSCALL1 for DosFreeModule sets up a
stack, "just in case a termination function needs to be called",
*before* it transfers into the kernel in the first place ?  Or do you mean
that when it needs to set up a ring 3 callback the kernel hand-crafts a
stack that, when the termination function returns, causes code in DOSCALL1
to be called ?

And how does the call gate that is the "return" from the InitTerm
function protect itself from malicious code that would otherwise use it as
a back door for entering the kernel at any place that it liked ?

 ¯ JdeBP ®

--- FleetStreet 1.19 NR
* Origin: JdeBP's point, using Squish (2:440/4.3)
SEEN-BY: 396/1 632/0 371 633/210 260 267 270 371 635/506 728 639/252 670/218
@PATH: 440/4 255/1 251/25 396/1 633/260 635/506 728 633/267

SOURCE: echomail via fidonet.ozzmosis.com

Email questions or comments to sysop@ipingthereforeiam.com
All parts of this website painstakingly hand-crafted in the U.S.A.!
IPTIA BBS/MUD/Terminal/Game Server List, © 2025 IPTIA Consulting™.