This is the mail archive of the cygwin@cygwin.com mailing list for the Cygwin project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

control-c issue when running VC++ console programs in bash.exe


Hi,

I've been having problems figuring out how to correctly handle control-c for
Visual C++ console programs run in cygwin bash.exe shell. After a related
post to this list, Troy Noble responded and we've been playing around with
some examples. Below is an example that illustrates some issues. I send this
to the list in the hopes that one of the cygwin gurus might be able to help
explain this behavior.

Try this experiment:
1. compile the program listing below using both g++
   and VC++ (command line is fine).
2. open up your NT/Win2k task manager.
3. open a bash window and then start up ctrlhandler.exe
   (the one compiled with VC++)
4. see how another bash.exe now shows up in your
   task manager processes list?
5. start up another bash window and run 'ps'
6. see how ctrlhandler shows up with the same
   PID in the 'ps' list as the bash.exe's PID in
   task manager?  That's not right.
   And the WINPID matches PID in the ps listing,
   which isn't right either I don't think.
   Also notice that this extra bash.exe is hidden
   and doesn't show up in the 'ps' process list.
7. control-c and watch output.
7. Repeat with cygwin compiled program. Notice task
   in task manager, and no "hidden" bash process.
8. control-c and compare output to VC++ program.

For the VC++ compiled program, When you press CTRL-C in the window this
results in the original bash.exe eventually calling into
signals.cc:kill_pgrp. It sends a kill(pid, SIGINT) to the hidden bash.exe,
which exits causing your win32 to exit immediately. Hence things like
destructors and other clean up functions don't get to execute.

Note that I've also tried POSIX signals. While this works great for cygwin
g++ programs run in bash.exe and VC++ compiled programs in DOS shell, it
does not work correctly for VC++ compiled programs run in bash.exe. You
basically end up with similar behavior to that mentioned above.

So, is this the expected behavior for running VC++ compiled program in
bash.exe? Can someone explain why VC++ compiled programs seem to run inside
a "hidden" bash.exe shell when viewed via Win NT/2K taskmanager? Is there a
correct way to handle control-c in VC++ compiled programs run in bash.exe?

VR, Charlie

PS thanks to Troy for his help in working on this issue.

------------- program ctrlhandler.cpp --------------------

// ctrlhandler.cpp
//
// Original program by Troy Noble [troy.noble@channelpoint.com]
// Some minor changes by Charlie Buckheit [bucweat_20657@yahoo.com]
//
// A program that sets up two WIN32 signal handlers to test
// how control-c is handled for a VC++ compiled program
// by cygwin as compared to one compiled with g++
//
// How to compile:
//     For cygwin use "g++ ctrlhandler.cpp -o cygwin_ctrlhandler"
//     For VC++ use "vcvars32", then "cl -GX ctrlhandler.cpp"
//
// Options:
//     -b swaps order that the control-c handlers are setup
//

#if defined (_WIN32) && !defined (__CYGWIN__)
#pragma warning(disable:4786)
#else
#include <unistd.h>
#endif

#include <windows.h>
#include <iostream.h>
#include <process.h>

static BOOL WINAPI ctrl_c_handler (DWORD);
static BOOL WINAPI ctrl_c_handler2 (DWORD);

static int bRun = true;

// Keyboard interrupt handler.
static BOOL WINAPI ctrl_c_handler (DWORD type)
{
    cout << "ctrl_c_handler  type=" << type
        << " pid=" << _getpid() << endl;

    // If I got a CTRL-C or CTRL-BREAK I want to do my
    // cleanup and exit gracefully now
    if (type == CTRL_C_EVENT || type == CTRL_BREAK_EVENT)
    {
        // do your cleanup code

        cout << "cleanup time.  set bRun=false" << endl;
        bRun = false;
        cout << "ctrl_c_handler done." << endl;

		int count = 0;
        while( ++count < 10 )
		{
			cerr << " " << count;
			Sleep(1000);
		}

        return TRUE;  // Notify not to call other handlers.
    }

    // Note: you want want to handle CTRL_LOGOFF_EVENT,
    // CTRL_CLOSE_EVENT, or CTRL_SHUTDOWN_EVENT in
    // some form or another as well here.  See MSDN
    // docs on SetConsoleCtrlHandler & friends as well
    // as winsup/cygwin/exceptions.cc:ctrl_c_handler
    // which is a pretty good example.

    // Otherwise let other ctrl handler have crack at it
    return FALSE;
}

// Keyboard interrupt handler.
static BOOL WINAPI ctrl_c_handler2 (DWORD type)
{
    // If I got a CTRL-C or CTRL-BREAK I want to do my
    cout << "ctrl_c_handler#2  type=" << type
        << " pid=" << _getpid() << endl;

	int count = 64;
	while( ++count <= 74 )
	{
		cerr << " " << (char)count;
		Sleep(1000);
	}
    // Always let other ctrl handler have a crack at it
    return FALSE;
}

int main(int argc, char* argv[])
{
    // variable declarations and whatnot ...
    bool bBefore =
        (argc > 1 && stricmp(argv[1], "-b") == 0);

    if (bBefore) {
        // Setup SECOND console ctrl handler BEFORE
        if (!SetConsoleCtrlHandler (ctrl_c_handler2, TRUE))
            cerr << "SetConsoleCtrlHandler #2 failed." << endl;
        cout << "Second control handler registered first." << endl;
    }

    // Setup SECOND console ctrl handler BEFORE
    if (!SetConsoleCtrlHandler (ctrl_c_handler, TRUE))
        cerr << "SetConsoleCtrlHandler failed." << endl;

    // your code here

    if (!bBefore) {
        // Setup SECOND console ctrl handler AFTER
        if (!SetConsoleCtrlHandler (ctrl_c_handler2, TRUE))
            cerr << "SetConsoleCtrlHandler #2 failed." << endl;
        cout << "Second control handler registered second." << endl;
    }

	cout << endl;

    while (bRun) {
       cout  << endl << "Sleep a little. ";
       Sleep(2000);
    }
    cout << "bRun is false.  Exiting." << endl;

    return 0;
}



_________________________________________________________
Do You Yahoo!?
Get your free @yahoo.com address at http://mail.yahoo.com


--
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple
Bug reporting:         http://cygwin.com/bugs.html
Documentation:         http://cygwin.com/docs.html
FAQ:                   http://cygwin.com/faq/


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]