Project

General

Profile

Bug #2901

Application sessions are not always terminated cleanly

Added by Eivind Midtgård over 8 years ago. Updated about 8 years ago.

Status:
Feedback
Priority:
Normal
Assignee:
Target version:
Start date:
04/04/2014
Due date:
% Done:

0%

Estimated time:

Description

On Windows: When I generate a CTRL_CLOSE_EVENT (by pressing the 'close button'), the program stops and my application objects are not destructed. WebSession::~WebSession is not called. It works when I generate a CTRL_C_EVENT (by pressing ctrl-C).

if (server.start())
{
    Wt::WServer::waitForShutdown();
    server.stop();
}

I had this problem in another program a long time ago. There I made the handler routine wait until the main thread reported that it had terminated:

HANDLE g_processStopEvent      = ::CreateEvent(0, 1, 0, 0);
HANDLE g_privateStopIsComplete = ::CreateEvent(0, 0, 0, 0);

BOOL WINAPI console_ctrl_handler(DWORD dwCtrlType)
{
    DWORD timeout = 4500;

    switch(dwCtrlType)
    {
    case CTRL_C_EVENT:      // Fall through
    case CTRL_BREAK_EVENT:
    case CTRL_CLOSE_EVENT:
        timeout = 4500;     // A little shorter than the hardcoded value in Windows
        break;

    case CTRL_LOGOFF_EVENT: // Fall through
    case CTRL_SHUTDOWN_EVENT:
    default:
        timeout = 19000;    // A little shorter than the hardcoded value in Windows
        break;
    }

    ::SetEvent(g_processStopEvent);  // Signal process it must stop

    // Wait for stop to complete, but no longer than the hardcoded timeout in Windows (5 seconds, or 20 seconds)
    ::WaitForSingleObject(g_privateStopIsComplete, timeout);
    Sleep(100);        // Just to make sure the main thread has a chance to finish completely
    return TRUE;
}

Regards,

Eivind

#1

Updated by Koen Deforche over 8 years ago

  • Status changed from New to InProgress
  • Assignee set to Wim Dumon
  • Target version changed from 3.3.2 to 3.3.3
#2

Updated by Wim Dumon over 8 years ago

  • Status changed from InProgress to Feedback

Well spot, I learned today about Windows' signal handling :-)

My conclusion: Wt's waitForShutdown is a generic method, which is in many cases doing what you want. But I can imagine very well that you don't want your application to terminate without cleanup on the 'special signals' CTRL_CLOSE_EVENT, CTRL_LOGOFF_EVENT, and CTRL_SHUTDOWN_EVENT.

My recommendation to you, is not to use Wt's waitForShutdown() since you want to handle the special signals in a special way, but to write your own. We can never know when your application cleaned up its state, at most we could know when all WServer objects are deleted (but we currently don't maintain a list). Any solution we would come up with, would not work for a certain use case.

Does this make sense?

Wim.

#3

Updated by Eivind Midtgård over 8 years ago

Hi Wim,

I'll try that. I had hoped that you could use my code as a starting point. (I would have tried reimplementing your waitForShutdown myself, but so far I have not been able to compile Wt with CMake, and each time I have tried compiling other systems with CMake something has gone wrong, so I have given up on CMake: I now pretend it doesn't exist. Maybe I should try once more.)

There is one thing I need to know: In your console_ctrl_handler you do this:

    boost::mutex::scoped_lock terminationLock(terminationMutex);
    terminationRequested = true;
    terminationCondition.notify_all(); // should be just 1

Is that something that my code has to do? If so, I believe it will be necessary to add a function to Wt that user-written 'waitForShutdown' functions will have to call when they have finished waiting, so that you have a place to put Wt cleanup code. Also, I wonder if implementing a shutdown function myself will interfere with WRun, which calls your waitForShutdown. I don't use WRun, but it is a pity if all Windows users will have to implement their own waitForShutdown.

Regards,

Eivind

#4

Updated by Wim Dumon about 8 years ago

Hi Eivind,

Wt's waitForShutdown() really simply blocks until ctrl-c has been pressed. It uses a boost mutex and a boost condition variable to transfer the event from the console_ctrl_handler to the thread that is blocked by waitForShutdown().

With respect to WRun, you don't have to use Wt's WRun. The documentation of WRun shows you its implementation. Copy-paste that in your project, and replace waitForShutdown() with your version of waitForShutdown().

What I could do, is add a sleep of e.g. 5 seconds at the end of console_ctrl_handler(). Is my assumption correct that if main() exits, this thread will be terminated too? That would then mean that the default waitForShutdown() would give the application at most a few seconds to terminate cleanly. If your application needs more time, you'd have to write your own.

BR,

Wim.

#5

Updated by Koen Deforche about 8 years ago

  • Target version changed from 3.3.3 to 3.3.4

Also available in: Atom PDF