Discussion:
out-of-proc COM object's process doesn't exit after our process do
(too old to reply)
ultranet
2005-09-13 21:55:05 UTC
Permalink
We are ensuring the following:
Each COM thread is CoInitializeEx'ed, and when we exit CoUninitialize'd.

outofproc.CreateInstance(__uuidof(MyClass));
eventSink.DispEventAdvise(outofproc);
// outofproc is then passed in to a constructor which has IOutofprocPtr& var
assigned from it, but i am sure this doesn't increase ref count.

is offset by
eventSink.DispEventUnadvise(outofproc);
outofproc = NULL; // force release
When we exit from our process.

Could this be by design of the 3rd-party COM object? Or does this mean
something is amiss for sure?
2005-09-14 04:36:08 UTC
Permalink
eventSink.DispEventAdvise(outofproc);
You'd better call QueryInterface for outofproc in order to increase ref
count inside DispEventAdvise.

You can create another simple executable in order to investigate behaviour
of that out of process component.

outofproc.CreateInstance(__uuidof(MyClass));
outofproc.SomeSimpleCall();
outofproc = NULL;

it shall be as simple as possible.
Post by ultranet
Each COM thread is CoInitializeEx'ed, and when we exit CoUninitialize'd.
outofproc.CreateInstance(__uuidof(MyClass));
eventSink.DispEventAdvise(outofproc);
// outofproc is then passed in to a constructor which has IOutofprocPtr& var
assigned from it, but i am sure this doesn't increase ref count.
is offset by
eventSink.DispEventUnadvise(outofproc);
outofproc = NULL; // force release
When we exit from our process.
Could this be by design of the 3rd-party COM object? Or does this mean
something is amiss for sure?
ultranet
2005-09-15 20:58:01 UTC
Permalink
Post by ultranet
eventSink.DispEventAdvise(outofproc);
You'd better call QueryInterface for outofproc in order to increase ref
count inside DispEventAdvise.
You can create another simple executable in order to investigate behaviour
of that out of process component.
outofproc.CreateInstance(__uuidof(MyClass));
outofproc.SomeSimpleCall();
outofproc = NULL;
it shall be as simple as possible.
It works in a simple sample w/ 1 STA thread (main). But in our development
code, we have a bunch of Java threads initied to MTA, which call methods on
the out-of-proc component. Everything works as expected, but out-of-proc
component's process doesn't exit when we do, even though we uninit COM on the
threads before exiting from them, and set out-of-proc component pointer to
NULL.

Does this mean that access to the out-of-proc component should be serialized
to a single STA thread, and JNI calls from Java SendMessage'd to that STA
thread?

P.S. What could be the underlying problem?

Thanks.
ultranet
2005-09-15 22:58:02 UTC
Permalink
I suspect that the root cause of this is that the out-of-proc component still
has some window messages in its queue. So does this always happen when an STA
component is used by MTA threads?
The looks a lot cleaner when using the component from MTA threads. The
alternative appears to be to SendMessage every method call to a single STA
thread.
ultranet
2005-09-16 04:45:02 UTC
Permalink
I almost decided today that the reason out-of-process component's process
didn't exit is because the component is Default-threaded (STA0), and our
client accesses it from MTA threads. I was going to use the snippet of code
from
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dncomg/html/comthreading.asp
to make an STA, w/ a loop, and deliver method calls to it using a CEvent,
and a vector.

But the same article, and
http://support.microsoft.com/kb/q150777/
and other sources i now recall reading in the past, notice that out-of-proc
components can be used from clients that use any threading model. So that
means us using MTA threads to create and use out-of-proc component is totally
OK.

Why is it then, that the out-of-process component's process exits when
running a simple test where it's created in STA0, main thread, and it doesn't
exit in a similar simple test when it's created on Java main thread that is
inited an MTA? It also doesn't exit when using the actuall app, where again
it's created and used by MTA threads?

Does this table reference from the 2nd link apply to out-of-proc server as
well?
MTA None Proxy access; server loaded into STA0; STA0 created
automatically by COM if necessary;
If so, could the problem be due to nobody doing CoUninitialize on the
auto-created STA?

Thanks.
Alexander Nickolov
2005-09-16 17:28:21 UTC
Permalink
COM does not create an STA thread for out-of-proc servers.
You are not reading carefully. This only applies to in-proc STA
servers hosted by an MTA client.

I'd suspect your referrence counting. Try converting your simple
sample to use MTA and see if it still works. It should...
--
=====================================
Alexander Nickolov
Microsoft MVP [VC], MCSD
email: ***@mvps.org
MVP VC FAQ: http://www.mvps.org/vcfaq
=====================================
Post by ultranet
I almost decided today that the reason out-of-process component's process
didn't exit is because the component is Default-threaded (STA0), and our
client accesses it from MTA threads. I was going to use the snippet of code
from
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dncomg/html/comthreading.asp
to make an STA, w/ a loop, and deliver method calls to it using a CEvent,
and a vector.
But the same article, and
http://support.microsoft.com/kb/q150777/
and other sources i now recall reading in the past, notice that out-of-proc
components can be used from clients that use any threading model. So that
means us using MTA threads to create and use out-of-proc component is totally
OK.
Why is it then, that the out-of-process component's process exits when
running a simple test where it's created in STA0, main thread, and it doesn't
exit in a similar simple test when it's created on Java main thread that is
inited an MTA? It also doesn't exit when using the actuall app, where again
it's created and used by MTA threads?
Does this table reference from the 2nd link apply to out-of-proc server as
well?
MTA None Proxy access; server loaded into STA0; STA0 created
automatically by COM if necessary;
If so, could the problem be due to nobody doing CoUninitialize on the
auto-created STA?
Thanks.
ultranet
2005-09-16 18:27:07 UTC
Permalink
Post by Alexander Nickolov
COM does not create an STA thread for out-of-proc servers.
You are not reading carefully. This only applies to in-proc STA
servers hosted by an MTA client.
Yes, i knew that the table only applies to in-proc components, and i
mentioned it in my post. But i was wondering if maybe an STA was instantiated
for out-of-proc once too.
Post by Alexander Nickolov
I'd suspect your referrence counting. Try converting your simple
sample to use MTA and see if it still works. It should...
Ref-counting should be fine, because attempting to Release 1 more time
causes a crash, IIRC from a couple of days ago.
You are right: converting simple sample to MTA also works (that was my last
thought to check last night too).

This is what i have found:
when the Java-main-based sample (closer to real code) involves
AfxBeginThread which i call in response to a user action pumped into event
sink (subclass of IDispEventImpl) sometimes, the external process doesn't
exit. If it doesn't involved AfxBeginThread, it does exit.

So there is something about the code that does AfxBeginThread that appears
to cause this. I basically call a short method:
UINT MyClass::PromptToSaveIfModifiedAndHide(LPVOID pParam)
{
CoInitializeEx(NULL, COINIT_MULTITHREADED);
// do some stuff here, involving HDC
CoUninitialize();
return result;
}

What can it possibly be? I gave up on making 1 re-usable thread for this
task, but maybe i should re-consider that? Or maybe i should perform this on
the same thread the callback comes on (it was causing a deadlock that way,
that's why i started using a worker thread)?

Thanks.
ultranet
2005-09-16 20:31:02 UTC
Permalink
Post by ultranet
What can it possibly be? I gave up on making 1 re-usable thread for this
task, but maybe i should re-consider that? Or maybe i should perform this on
the same thread the callback comes on (it was causing a deadlock that way,
that's why i started using a worker thread)?
I thought it could have been because of GetBitmap, or SetClipboardData, but
even when those calls aren't made, as long as the thread is spawned, the
external process doesn't exit.
ultranet
2005-09-16 20:57:09 UTC
Permalink
Post by ultranet
I thought it could have been because of GetBitmap, or SetClipboardData, but
even when those calls aren't made, as long as the thread is spawned, the
external process doesn't exit.
This is getting weird: i disabled AfxBeginThread call as well as screen
captue, and GetBitmapBits, and external process doesn't exit when 3rd-party's
OnLogoutQuery event sink callback gets called in response to trying to
manually close their window, where we set a flag to 0 to say don't log off.
The strange part is that the same method is later called again during our
process's exiting, where we set the flag to 1, telling it to exit. So if we
ever once set it to 0 in response to user action, their process doesn't exit,
even though we later set the flag to 1 in response to another callback based
on API call to logout.

Is it just me, or does this sound like a 3rd-party defect? We already found
and worked around one defect for them. This really sounds like another one.
ultranet
2005-09-16 21:13:04 UTC
Permalink
Misspelled one sentence in last post:

... where we set the flag to 1, telling it to log out (current user that
is). So if we ...
Alexander Nickolov
2005-09-16 22:49:13 UTC
Permalink
You need to check with the 3rd party developers. Try to
reproduce it in your sample project so you can give them the
source showing the problem.
--
=====================================
Alexander Nickolov
Microsoft MVP [VC], MCSD
email: ***@mvps.org
MVP VC FAQ: http://www.mvps.org/vcfaq
=====================================
Post by ultranet
... where we set the flag to 1, telling it to log out (current user that
is). So if we ...
ultranet
2005-09-17 01:04:01 UTC
Permalink
Post by Alexander Nickolov
You need to check with the 3rd party developers. Try to
reproduce it in your sample project so you can give them the
source showing the problem.
Must be telepathy (;) ):
that was my thinking too, after ruling out everything in our code.
I modified the simple sample slightly, and confirmed that performing the
same step as in integrated app we have in this simple sample causes the same
problem:
i.e., after logout event is pumped into the event sink, and user is
apparently logged out, and after ref count went to 0, the out-of-proc
server's process is still running. Moreover, if the out-of-proc server's
window isn't hidden before this, and a UI action is taken, the external
process crashes (by this time our process is long gone). Not taking the
action in the middle is simple sample, leads to server process exiting as
expected.

This is the 3rd defect we came across in this project. 1 was in ATL in VC
6.0, another one in 3rd party API, and now this one.The first one had a
work-around already. The 2nd one, i worked around w/ some tips from this
board. The 3rd one i can't work around: goes to the 3rd party. Nice labor
division, huh? ;)

Continue reading on narkive:
Loading...