Discussion:
Lifetime management of InProc server inside an OutProc server
(too old to reply)
Stuart Redmann
2010-04-14 14:03:51 UTC
Permalink
Hello newsgroup,

I have the following problem with COM: I have a component inside an
OutProc server that is used by my application. This OutProc component
creates some InProc components that are used by application. Atfer
that, this OutProc component is not used any longer by the
application, so it is Release'd. Unfortunately, the OutProc server
will shut down because the ATL module management code thinks that all
components have been released. Upon shutdown the OutProc server will
destroy all those Inproc components that are still referenced by the
application!

I can think of two solutions to this problem:

(A) the COM standard says somewhere that you must not create InProc
components inside OutProc servers (unless you know that the life-time
of the OutProc components will extend the lifetime of the InProc
components). I could not find anything about this in my copy of Don
Box but that doesn't mean that such a restriction could not be out
there somewhere (I more or less accidentally found that one must not
make inter-apartment calls inside WM_PAINT handling routines on MSDN).

(B) The ATL implementation of InProc module life-time management is
faulty. I think that an easy way to avoid the problem would be to
launch some dummy thread during DllMain of InProc servers, thus
ensuring that the process of the OutProc server will only terminate
when all InProc servers can be unloaded safely.

Thanks in advance,
Stuart
Brian Muth
2010-04-14 16:47:38 UTC
Permalink
Why don't you change this to an ATL service? It's the perfect answer.
Post by Stuart Redmann
Hello newsgroup,
I have the following problem with COM: I have a component inside an
OutProc server that is used by my application. This OutProc component
creates some InProc components that are used by application. Atfer
that, this OutProc component is not used any longer by the
application, so it is Release'd. Unfortunately, the OutProc server
will shut down because the ATL module management code thinks that all
components have been released. Upon shutdown the OutProc server will
destroy all those Inproc components that are still referenced by the
application!
(A) the COM standard says somewhere that you must not create InProc
components inside OutProc servers (unless you know that the life-time
of the OutProc components will extend the lifetime of the InProc
components). I could not find anything about this in my copy of Don
Box but that doesn't mean that such a restriction could not be out
there somewhere (I more or less accidentally found that one must not
make inter-apartment calls inside WM_PAINT handling routines on MSDN).
(B) The ATL implementation of InProc module life-time management is
faulty. I think that an easy way to avoid the problem would be to
launch some dummy thread during DllMain of InProc servers, thus
ensuring that the process of the OutProc server will only terminate
when all InProc servers can be unloaded safely.
Thanks in advance,
Stuart
Stuart Redmann
2010-04-15 06:49:21 UTC
Permalink
Post by Brian Muth
Post by Stuart Redmann
Hello newsgroup,
I have the following problem with COM: I have a component inside an
OutProc server that is used by my application. This OutProc component
creates some InProc components that are used by application. Atfer
that, this OutProc component is not used any longer by the
application, so it is Release'd. Unfortunately, the OutProc server
will shut down because the ATL module management code thinks that all
components have been released. Upon shutdown the OutProc server will
destroy all those Inproc components that are still referenced by the
application!
[snip]
Post by Brian Muth
Why don't you change this to an ATL service? It's the perfect answer.
Thanks for the suggestion, that's a good idea.

However, I feel that it is still some kind of work-around (else you
can cite me some MSDN site that says that COM components that create
another components must be run inside a Service). I fixed my problem
by making the component that is created by the other component also an
OutProc component.

What is still an interesting question to me is whether ATL's module
life-time management is flawed or whether I am doing things that are
not meant to be done (creating InProc components inside OutProc
servers is not prohibited by COM in any way, so one should assume that
it is perfectly legal to do so).

Thanks,
Stuart
Igor Tandetnik
2010-04-15 12:04:20 UTC
Permalink
Post by Stuart Redmann
What is still an interesting question to me is whether ATL's module
life-time management is flawed
No. You have two independent modules here, each correctly managing its own lifetime and that of its objects. The problem is, your EXE server is handing out somebody else's pointers as if they were its own, but takes no steps to ensure that it outlives those objects. On the other hand, all a DLL server can do is return false from DllCanUnloadNow and hope that someone cares - it cannot prevent the hosting process from terminating.
Post by Stuart Redmann
or whether I am doing things that are
not meant to be done (creating InProc components inside OutProc
servers is not prohibited by COM in any way
It's not. But handing out interface pointers from that InProc server to out-of-process clients has to be done with extra care.
--
With best wishes,
Igor Tandetnik

With sufficient thrust, pigs fly just fine. However, this is not necessarily a good idea. It is hard to be sure where they are going to land, and it could be dangerous sitting under them as they fly overhead. -- RFC 1925
Stuart Redmann
2010-04-15 14:43:56 UTC
Permalink
Post by Igor Tandetnik
Post by Stuart Redmann
What is still an interesting question to me is whether ATL's module
life-time management is flawed
No. You have two independent modules here, each correctly
managing its own lifetime and that of its objects. The problem
is, your EXE server is handing out somebody else's pointers
as if they were its own, but takes no steps to ensure that it
outlives those objects. On the other hand, all a DLL server
can do is return false from DllCanUnloadNow and hope that
someone cares - it cannot prevent the hosting process from terminating.
Well, one could argue that the COM specification offers no means to
prevent the hosting process from terminating (at the time COM was
designed no-one seemed to anticipate such a case), but we could do it
by letting the InProc server launch a dummy thread per attached
process whose sole purpose is to keep the host process alive.
Admittedly, this seems to be a horrific work-around for what I think
is a minor deficiency in the COM specification, but it would prevent
some people (like me ;-) from falling into some non-obvious traps (or
is this an obvious issue?)

Thanks,
Stuart
Igor Tandetnik
2010-04-15 21:20:20 UTC
Permalink
Post by Stuart Redmann
Well, one could argue that the COM specification offers no means to
prevent the hosting process from terminating (at the time COM was
designed no-one seemed to anticipate such a case), but we could do it
by letting the InProc server launch a dummy thread per attached
process whose sole purpose is to keep the host process alive.
I don't see how that would help. Normally, when a process decides to terminate, it will simply allow WinMain to return, at which point CRT calls ExitProcess. This will terminate all threads still running.

Further, before exiting, WinMain will likely call CoUninitialize, so even if by some miracle the process is not terminated and the DLL server survives, it will find it difficult to do any COM work.

Further still, in-proc servers often rely on their host process to run a message pump for them. If the process decides to terminate, it'll likely exist its message pump first thing.
--
With best wishes,
Igor Tandetnik

With sufficient thrust, pigs fly just fine. However, this is not necessarily a good idea. It is hard to be sure where they are going to land, and it could be dangerous sitting under them as they fly overhead. -- RFC 1925
Stuart Redmann
2010-04-16 07:56:43 UTC
Permalink
Post by Igor Tandetnik
Post by Stuart Redmann
Well, one could argue that the COM specification offers no means to
prevent the hosting process from terminating (at the time COM was
designed no-one seemed to anticipate such a case), but we could do it
by letting the InProc server launch a dummy thread per attached
process whose sole purpose is to keep the host process alive.
I don't see how that would help. Normally, when a process decides
to terminate, it will simply allow WinMain to return, at which point
CRT calls ExitProcess. This will terminate all threads still running.
Gosh, I didn't realize this. For some reasons I used to believe that a
process will only terminate when the last of its threads ends.
Post by Igor Tandetnik
Further, before exiting, WinMain will likely call CoUninitialize, so
even if by some miracle the process is not terminated and the
DLL server survives, it will find it difficult to do any COM work.
Further still, in-proc servers often rely on their host process to
run a message pump for them. If the process decides to terminate,
it'll likely exist its message pump first thing.
That's exactly what was going through my mind last evening when I was
about to go to sleep. However, I didn't want to wake up the children
so I decided to post this here as soon as I get in to work.
Apparently, you stand up a bit earlier.

Thank you,
Stuart

Loading...