2

I have an MFC Dialog app that runs in the notification area (the system tray). It occasionally just shuts down with no rhyme or reason.

After years of fighting this, thinking it was memory corruption or something, I added some logging.

It turns out that I'm receiving WM_CLOSE messages from somewhere. But I don't know where. I have some forced shut-down code of my own for updates and such but they are well logged and are never firing.

An interesting thing is that my app has to do a bit of cleanup, to make sure it isn't in the middle of a database operation. So inside OnClose() I actually don't close right away but set a flag and the next time my task timer fires if OnClose() has been called, it gets called again to truly shut down the app.

So what I see in the logs is a half dozen OnClose() calls in rapid succession (milliseconds apart) and then the program just goes away. It never calls my actual post-cleanup OnClose() because my timer is on 5 seconds interval so my cleanup starts but my shutdown never gets called.

I can't help but think these calls are coming from an external process - Windows update or something - and occasionally the Windows system event logs indicate a security update or gupdate.exe firing around that time. But the computer doesn't even restart. It just looks like something sends half a dozen Close messages to me and then kills the program.

I think I'm losing my mind - is some external process truly shutting down my app? Or am I entirely on the wrong path here?

Maybe I'm not following best-practices in some ways but I'm struggling with this. This app needs to be running (a monumental effort to change to service, btw) 24/7 but I keep getting these unexpected disappearances.

(Edit) As requested, I've added the OnClose() code here. The first time in (in the else) I set a flag indicating that we're waiting to close. When the timer next fires, it sees this flag, sets CloseNow and calls OnClose()

When this situation happens I see multiple "waiting to close" messages in the log but it never gets into the CloseNow condition to shut down properly. But the app gets shut down.

There's nothing in my code that would send multiple OnClose messages. I thought it might be the processmessages() thing at first, but it never even gets there.

void CBPTillBotDlg::OnClose()  {

// Got a close message, tell timer we're shutting down.
m_iKillingApplication = true;
InstallIcon(NIM_MODIFY,MODE_IDLE);


// if the timer has returned and says it is okay to close now
if (m_iCloseNow) {

    // On a normal close when the timer sets m_iCloseNow
    // we fall into here and cleanup.
    // *** With the OnClose() problem, this code never gets hit.

    BECLog lLog;

    lLog.WriteString("CBPTillBotDlg::OnClose() Stopping Timer");

    m_btTimer->StopTimer();

    lLog.WriteString("CBPTillBotDlg::OnClose() Calling Getfields()");

    GetFields(); 

    lLog.WriteString("CBPTillBotDlg::OnClose() Kill Tabs");
    if (m_pdImport!=NULL) {
        m_pdImport->DestroyWindow();
        delete m_pdImport;
        m_pdImport = NULL;
    }
    if (m_pdExport!=NULL) {
        m_pdExport->DestroyWindow();
        delete m_pdExport;
        m_pdExport = NULL;
    }
    if (m_pdBackup!=NULL) {
        m_pdBackup->DestroyWindow();
        delete m_pdBackup;
        m_pdBackup = NULL;
    }
    if (m_pdError!=NULL) {
        m_pdError->DestroyWindow();
        delete m_pdError;
        m_pdError = NULL;
    }
    if (m_pdReport!=NULL) {
        m_pdReport->DestroyWindow();
        delete m_pdReport;
        m_pdReport = NULL;
    }

    lLog.WriteString("CBPTillBotDlg::OnClose() Save Config");
    m_tbCfg->Save(); 

    lLog.WriteString("CBPTillBotDlg::OnClose() Delete Literals");
    if (m_pLiteral!=NULL) {
        delete (m_pLiteral);
        m_pLiteral = NULL;
    }

    lLog.WriteString("CBPTillBotDlg::OnClose() Shut Down Normally");

    ProcessMessages();
    Sleep(0);
    CDialog::OnClose();
}
else {
    // First time WM_CLOSE
    // Set WaitToClose to indicate that we're closing.
    // The next time the timer fires (which means we're done current processing) the timer knows to set m_iCloseNow
    // *** With OnClose() problem, we're coming in here multiple times and not from any of our code. 
    m_bWaitToClose = TRUE;

    BECLog lLog;
    lLog.WriteString("CBPTillBotDlg::OnClose() Bot Waiting to Close");
}

}

KokoCa
  • 131
  • 9
  • 1
    Can you show us the code for your `OnClose()` handler? That would help us to diagnose the problem. – Adrian Mole Jan 27 '20 at 15:16
  • Thanks for taking a look. I've added the code and a bit of explanation into the original post. – KokoCa Jan 27 '20 at 16:12
  • 1
    As a note (not a solution), Windows will forceably kill a process that is not responding to close messages. Is there a way for you to close and then re-open? – Topher Jan 27 '20 at 19:07
  • Thanks @Topher. I'm really puzzled why Windows is shutting down my apps. Is it generally considered best-practices when you have an app that should be running all the time to anticipate that other things are going to force close and make plans to monitor and restart it? – KokoCa Jan 27 '20 at 23:33
  • Yes, agreed. This is very puzzling. – Topher Jan 28 '20 at 00:09
  • 1
    Just a thought... if you capture WM_CLOSE and return 0 (zero) you may be able to short-circuit the kill (it will stop the WM_DESTROY). However, if you are also using WM_CLOSE to close yourself, then that may not be an option. – Topher Jan 28 '20 at 01:11
  • 1
    Could it be antivirus / firewall trying to shut it down? – Andrew Truckle Jan 28 '20 at 11:23
  • Thanks @Topher - I am using WM_CLOSE myself but I think I know when I'm using it, if that makes sense. So I might be able to make something like that work. – KokoCa Jan 28 '20 at 18:04
  • @AndrewTruckle- I've actually tried whitelisting the app in AV. Still does it. I think it is an intentional shutdown by an updater of some sort. Hard to track down :) – KokoCa Jan 28 '20 at 18:04
  • @Topher I like your idea of trying to short-circuit WM_CLOSE. Although my app is using it, I think I can work around that by determining when the close is intentional or permitted. But I'm puzzled, or obtuse, how do you return something OnClose() is a void return function. So is OnSystemCommand (if trapping SC_CLOSE). Clearly I'm missing something? Thanks! – KokoCa Jan 31 '20 at 23:23
  • 1
    You will have to catch it through the WindowProc function. https://learn.microsoft.com/en-us/windows/win32/winmsg/wm-close – Topher Feb 03 '20 at 18:26

0 Answers0