after
int nResponse = dlg.DoModal();
CoUninitialize();
I call (just to be able to catch the error):
int err = theApp.ExitInstance();
err returns = 20.
I traced into thrdcore.cpp, below.
MSG* AFXAPI AfxGetCurrentMessage()
{
_AFX_THREAD_STATE* pState = AfxGetThreadState();
ASSERT(pState);
return &(pState->m_msgCur);
}
There is obviously a thread wtill running - as I saw in the Thread
list:
3084 __tmainCRTStartup CCamelotSampleApp::InitInstance Normal 0
2244 Win32 Thread _KiFastSystemCallRet@0 Normal 0
How do I ensure that the GUI thread closes before the application
does?
Thanks,
Mechi
>Hi!
>I have a dialog based application. It always exits with 20 - though i
>think it should exit with 0. The only thread that is opened is the
>GUI/dialog itself. I open and then immediately (afte GUI is
>displayed) close the application.
>
>after
> int nResponse = dlg.DoModal();
>
> CoUninitialize();
>
>I call (just to be able to catch the error):
>
> int err = theApp.ExitInstance();
>
>err returns = 20.
>
>I traced into thrdcore.cpp, below.
>
> MSG* AFXAPI AfxGetCurrentMessage()
> {
> _AFX_THREAD_STATE* pState = AfxGetThreadState();
> ASSERT(pState);
> return &(pState->m_msgCur);
> }
****
Yes, but what does this piece of information have to do with the call on ExitInstance? You
did not show us the call stack at the point where you claim to be in this code, so how are
we to guess who called it, or why?
One thing we usually know to do is to completely and utterly ignore the return codes from
GUI-based applications. Not sure why you care that it is 20.
****
>
>There is obviously a thread wtill running - as I saw in the Thread
>list:
****
It is not clear what the '20' has to do with making it obvious a thread is running; yes,
it is obvious from the thread display you show, but the thread display merely shows the
threads that are running. It says nothing about who is responsible for cleaning them up.
With a name like 'KiFastSystemCallRet', it looks like some internal thread, and you can
expect that it has something to do with system calls, and it will probably be cleaned up
by the exit code.
****
> 3084 __tmainCRTStartup CCamelotSampleApp::InitInstance Normal 0
> 2244 Win32 Thread _KiFastSystemCallRet@0 Normal 0
>
>
>How do I ensure that the GUI thread closes before the application
>does?
****
I'm not sure what you are talking about here. Unless you are using multiple threads,
closing the GUI thread indeed closes the application, by definition. If you are using
multiple threads, it is your responsibility to see that all these threads are properly and
cleanly terminated before you allow the main GUI thread to exit. You have not actually
determined that the standard OnExit handler does not clean up this other thread. In fact,
you do not seem to have indicated where you are stopped when you do this display. Note
that ExitInstances is a LONG distance from terminating the GUI thread; it might yet have
millions of instructions to execute at that point, for all you know. Unless you trace the
code beyond this point, you have no idea what is going to happen. So you don't know if
that mysterious thread is going to be terminated by some library somewhere before the main
thread exits.
joe
*****
>Thanks,
>Mechi
Joseph M. Newcomer [MVP]
email: newc...@flounder.com
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm
In a dialog application, you typically show the dialog in InitInstance(),
wait for the DoModal() call to return, then return FALSE from InitInstance()
so your app closes without starting a message pump.
Because you do not override ExitInstance() (and it is not even called) in
this scenario, you don't have the ability to set a proper return code.
Essentially the return code is garbage depending on the last message pumped,
I believe.
Bottom line is if you care about the return code, you can't call DoModal()
in InitInstance() like this. Instead you need to start a message pump so
that ExitInstance is called. This typically means showing a CMainFrame
(perhaps with no menu bar, toolbar, or status bar) containing a CFormView of
your original dialog.
> The only thread that is opened is the
> GUI/dialog itself. I open and then immediately (afte GUI is
> displayed) close the application.
>
> after
> int nResponse = dlg.DoModal();
>
> CoUninitialize();
>
> I call (just to be able to catch the error):
>
> int err = theApp.ExitInstance();
>
> err returns = 20.
>
I don't know how CWinApp::ExitInstance() determines it's return value, but
it doesn't really matter because there is no way for you to then set this
value to the return value of your app.
> I traced into thrdcore.cpp, below.
>
> MSG* AFXAPI AfxGetCurrentMessage()
> {
> _AFX_THREAD_STATE* pState = AfxGetThreadState();
> ASSERT(pState);
> return &(pState->m_msgCur);
> }
>
> There is obviously a thread wtill running - as I saw in the Thread
> list:
> 3084 __tmainCRTStartup CCamelotSampleApp::InitInstance Normal 0
> 2244 Win32 Thread _KiFastSystemCallRet@0 Normal 0
>
>
> How do I ensure that the GUI thread closes before the application
> does?
It does. But you haven't returned from CCamelotSampleApp::InitInstance()
yet when you look at the call stack; you are looking too early.
-- David
Just some minor corrections, although the bulk of your answer is on
target. CWinApp is derived from CWinThread, and when InitInstance
returns false, this leads to a call to pThread->ExitInstance. This
becomes a call to CWinApp::ExitInstance. If AfxGetCurrentMessage
returns a non-NULL current MSG pointer, then ExitInstance will return
the wParam from that message.
But Joe's reply about it being unusual to care about the return value
from GUI app is appropriate here. A simple debugging session should
yield the answers, though.
Thanks!
So I guess I can just ignore the return code.
This is the output from the IDE:
'CamelotSample.exe': Unloaded 'C:\WINDOWS\system32\devenum.dll'
'CamelotSample.exe': Unloaded 'C:\WINDOWS\system32\quartz.dll'
The thread 'Win32 Thread' (0xcc) has exited with code 0 (0x0).
No memory leaks detected.
The program '[2184] CamelotSample.exe: Native' has exited with
code 20 (0x14).
Thanks again for all the helpful advice and timely answers,
Mechi
Hmm, that's different than how I think it is. I did not think ExitInstance
gets called if InitInstance returns FALSE. If it were, it would be easy:
just override CWinApp::ExitInstance() and return the desired value, which
will be the value returned to the OS when the app exits.
> But Joe's reply about it being unusual to care about the return value from
> GUI app is appropriate here.
Well, mostly the return value is ignored, but not always. For example, some
GUI apps are typically launched from a script and run in automated mode; the
script would care about the return value to indicate an error in the
automated processing. For example, devenv.exe can be launched with a given
.sln file to do a build, in this case, no UI is shown but the return value
is important. So I don't think you can make a general rule that "The return
value of a GUI app is not important." Especially since you don't know in
advance how your users are going to use your app.
-- David
>"Scot Brennecke" <Sc...@spamhater.MVPs.org> wrote in message
>news:eRgXQOQY...@TK2MSFTNGP02.phx.gbl...
>> Just some minor corrections, although the bulk of your answer is on
>> target. CWinApp is derived from CWinThread, and when InitInstance returns
>> false, this leads to a call to pThread->ExitInstance. This becomes a call
>> to CWinApp::ExitInstance. If AfxGetCurrentMessage returns a non-NULL
>> current MSG pointer, then ExitInstance will return the wParam from that
>> message.
>>
>
>Hmm, that's different than how I think it is. I did not think ExitInstance
>gets called if InitInstance returns FALSE. If it were, it would be easy:
>just override CWinApp::ExitInstance() and return the desired value, which
>will be the value returned to the OS when the app exits.
****
I just read the code and it will call ExitInstance if InitInstance fails. thrcore.cpp
line 116.
****
>
>
>> But Joe's reply about it being unusual to care about the return value from
>> GUI app is appropriate here.
>
>Well, mostly the return value is ignored, but not always. For example, some
>GUI apps are typically launched from a script and run in automated mode; the
>script would care about the return value to indicate an error in the
>automated processing. For example, devenv.exe can be launched with a given
>.sln file to do a build, in this case, no UI is shown but the return value
>is important. So I don't think you can make a general rule that "The return
>value of a GUI app is not important." Especially since you don't know in
>advance how your users are going to use your app.
****
There are some very rare cases where the return type seems to be used, but they are very
rare indeed. In general, a user should not depend on the return code from a UI app unless
the app explicitly states that it guarantees the return code value.
joe
****
>
>-- David
Well lookee there! It sure does. Thanks, now it's very easy for a dialog
app to return any error code it wants; override ExitInstance()!
> There are some very rare cases where the return type seems to be used, but
> they are very
> rare indeed. In general, a user should not depend on the return code from
> a UI app unless
> the app explicitly states that it guarantees the return code value.
Well, yes, but that holds true to a console app as well (it is up to the
app, gui or not, to document return values).
-- David
Here's the REAL problem:
When I open and close the application again and again (without doing
anything - closing after the dialog is shown) it is usually OK.
Sometimes, though, I get one of those Microsoft dialog errors (Report
this error Yes/No) when I close the application. I'm trying to figure
out why this happens. what is not getting closed/taken care of.
How can I understand the Microsoft Error report? I thought that this
return code had to do with this - but the return code of 20 is
returned all the time - even when the application closes OK.
Thanks for any more hints and ideas,
Mechi
If the debug version crashes, then when it crashes (when the Report This
error dialog is showing), go to Visual Studio and select Debug | Attach to
process. Select your process from the list. Select Debug | Break all and
you will get a call stack where it crashed.
-- David
No - only the Release version crahses - that's what makes things
difficult. And - only sometimes...
Thanks,
Mechi