[omniORB] OmniORB in a COM object

Claudio Natoli claudio.natoli@memetrics.com
Tue, 20 Feb 2001 14:39:08 +1100


Hi David,

I've been secretly hoping that someone else (with better solutions than
we've found) would provide answers to this and your previous post, having
encountered the exact same problem without arriving at a satisfactory
solution.

Since that hasn't happened (as yet?) I'll throw in my 2 cents worth...


> I'm using OmniORB in a COM object.  This object is going to 
> be used in an
> Internet Server application so the dll that contains the 
> control will be
> started once, then multiple instances of the control will be 
> created by IIS.
> I have made the ORB and the root POA global objects in the application
> object that all instances of the control can access.  The 
> first instance of
> the control calls ORB_init() when it processes a command (not in its
> constructor).  What I can't have is the control calling 
> orb->destroy() as
> this would prevent any subsequent instances of the control 
> (in the same dll
> instance) working.  So I have tried putting destroy into the dll's
> ExitInstance() and the main dll application object's 
> destructor, but the
> application hangs in the call to destroy().


My understanding is as follows:

The underlying reason why the application hangs during the destroy() call is
because of the way the Windows kernel serializes calls to the DllMain
routine. Specifically, only 1 thread is ever allowed to attach to/detach
from/etc. a dll at any point in time... the kernel makes any other threads
which attempt to do so wait until the initial call completes.

In your case, the destroy() call causes one or more orb threads to
terminate, and waits for those terminations to complete. As part of their
termination, these threads will detach from any attached dll's. However, you
issue the destroy() call from ExitInstance, which is *itself* called from
DllMain... 

And therein lies the deadlock: The destroy() call won't return until the orb
threads terminate, and they won't terminate until the thread making the
ExitInstance call exits the DllMain routine.


> Can anyone tell me how I should handle this? 

Firstly, if you can place the destroy() call such that it is invoked prior
to the invocation of DllMain/ExitInstance (ie. some Terminate() function
that gets called prior to the DLL being unloaded), then do so. 

However, given that you chose to put the destroy() call in ExitInstance in
the first place, I'm guessing that this is the only logical place that you
have for this call to go. We faced the same situation ourselves some months
ago, and after a great deal of experimentation with alternative "solutions"
and purist soul-searching we came up with the following solution: don't call
orb->destroy().

In our (initial) application and I'm assuming in yours as well, the call to
ExitInstance will only arrive when IIS is itself terminating (so memory
leaks etc. associated with NOT calling destroy() are a bit of a moot point).
The purist in me still feels violated, but in the end we just needed to get
something going, and so the pragmatist won out! In any case, we didn't have
any problems with this approach, though your mileage may vary. [can you
guess how tell how uncomfortable I am recommending this?]


Another possible solution you may not have considered (or may not find
acceptable) is to use an out-of-process server rather than an in-process
DLL. You could simply initialise/terminate the orb from the WinMain
function, though keep in mind that, being OOP, you will cop a performance
hit. 


In addition, Renzo Tomaselli provided another possible solution in a
previous post
(http://www.uk.research.att.com/omniORB/archives/2000-03/0012.html), however
this is unlikely to be of use to you in an IIS application (though others
reading this may find it useful).

Best of luck,
Claudio

PS. All comments/suggestions/flames welcome!