Download as pdf or txt
Download as pdf or txt
You are on page 1of 5

Control Signal

How control signals are handled by


default?
By default a system thread is running against a process which
will handle the control signal. For example: when you press ctrl
+ c, it will handle by the system and system will call
ExitProcess() method to close your process.

How does we attach our own Control


Signal Handler?
We can add an event handler by simply adding the below code.
In other word, we are attaching our own event handler to the
process.

/* Add an event handler. */


if (!SetConsoleCtrlHandler(Handler, TRUE))
ReportError(_T("Error setting event handler"),
1, TRUE);

Here, Handler is a function which returns BOOL. The signature


of HANDLER function is as follow

static BOOL WINAPI Handler(DWORD cntrlEvent);

The ctrlEvent value is automatically pressed when you press ctrl


+ any other key to this function.

We can also detach our own event handler by simply putting


FALSE.
if (!SetConsoleCtrlHandler(Handler, FALSE))
ReportError(_T("Error detaching event handler"),
1, TRUE);

What happen we attach an control


signal Handler?
Basically, all the handler are stacked. On the bottom is the
SYSTEM EVENT HANDLER. When we attach our own EVENT
HANDLE that will be push on the top of the SYSTEM EVENT
HANDLER.

However, it depends upon our code of custom event Handler


that the control will propagate to the lower system event
handler or not. If our own EVENT HANDLER return TRUE it
indicates that our own EVENT HANDLER successfully controlled
the event and it doesn't need to go to the SYSTEM EVENT
HANDLER. But in case of FALSE it will be HANDLE by the
SYSTEM EVENT HANDLER.

BOOL WINAPI Handler(DWORD cntrlEvent)


{
switch (cntrlEvent) {
/* The signal timing will determine if you
see the second handler message */
case CTRL_C_EVENT:
_tprintf(_T("Ctrl-C received by handler.
Leaving in 5 seconds or less.\n"));
exitFlag = TRUE;
//Sleep(4000); /* Decrease this time to
get a different effect */
//_tprintf(_T("Leaving handler in 1
second or less.\n"));
return TRUE; /* TRUE indicates that the
signal was handled. */
case CTRL_CLOSE_EVENT:
_tprintf(_T("Close event received by
handler. Leaving the handler in 5 seconds or
less.\n"));
exitFlag = TRUE;
//Sleep(4000); /* Decrease this time to
get a different effect */
//_tprintf(_T("Leaving handler in 1
second or less.\n"));
return TRUE; /* Try returning FALSE. Any
difference? */
default:
_tprintf(_T("Event: %d received by
handler. Leaving in 5 seconds or less.\n"),
cntrlEvent);
exitFlag = TRUE;
//Sleep(4000); /* Decrease this time to
get a different effect */
//_tprintf(_T("Leaving handler in 1
seconds or less.\n"));
return FALSE; /* TRUE indicates that the
signal was handled. */
}
}

In Above code, ctrl+c event will be controlled by the our own


Event handler and control will not passed to system event
handler. But as you can see all other events except
CTRL_C_EVENT and CTRL_CLOSE_EVENT will goes to DEFAULT
block which is return FALSE which means they will be handled
by SYSTEM EVENT HANDLER. But if we return TRUE then no
event trigger by control signal will be handle by SYSTEM EVENT
HANDLER instead they will all get ignored by our OWN EVENT
HANDLER.
Difference between exception and
control signal?
The signal is for the whole process while exception is with
respect to the specific thread.

Why the control signal is related to


whole process instead of the thread?
One of the reason can be the control signal handler itself run as
the separate thread.

How to ignore Ctrl + C control signal?


Basically, Ctrl + c is a special case and there is a code which
allow us to ignore only ctrl+c not other ctrl signal such as
ctrl+break.

if (!SetConsoleCtrlHandler(NULL, TRUE))
ReportError(_T("Error setting event
handler"), 1, TRUE);

There is other way to ignore ctrl+c signal as well that is right


below

HANDLE hIn;
hIn = CreateFile (_T("CONIN$"), GENERIC_READ |
GENERIC_WRITE, 0,NULL, OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL, NULL);
SetConsoleMode (hIn, ENABLE_LINE_INPUT |
ENABLE_ECHO_INPUT );// since ENABLE_PROCESSED_INPUT
is not present, ctrl-c is ignored. However, ctrl-
break is still working.
What we are doing in above snippet is the ctrl+c will become
the part of the console input buffer and it will not get handle by
the system. Hence, it will get ignored.

You might also like