SetConsoleCtrlHandler и многопоточность
От: mityaj.it.0  
Дата: 18.09.09 09:19
Оценка:
Привет всем, есть такой код:
BOOL ConsoleHandler( DWORD fdwCtrlType )
{
    switch (fdwCtrlType) {
        case CTRL_C_EVENT: {
            std::cout << "Exit." << "\n";
                        exit(1);
        }

    }
}
int _tmain(int argc, _TCHAR* argv[])
    if (SetConsoleCtrlHandler( (PHANDLER_ROUTINE)ConsoleHandler,TRUE)==FALSE) {
        // unable to install handler... 
        return -1;
    }
    try {
        // Enable exceptions in cin.
        std::cin.exceptions(std::ios::badbit|std::ios::failbit);
        int itSum = 0;
        std::cin >> itSum;
    catch (...) {
        std::cout << "Error!" << "\n";
    }
}

Необходимо при ожидании ввода числа иметь возможность завершить программу по нажатию [Ctrl+C]. Данный код
это предоставляет, но с одним "НО": обработчик ConsoleHandler вызывается в другом потоке и основной поток также продолжает выполнение.
В итоге выполняется обработчик исключения и обработчик [Ctrl+C]. Это некорректно. Каким образом затормозить основной поток или
дать ему понять, что нажата [Ctrl+C]?


23.09.09 20:26: Перенесено модератором из 'C/C++. Прикладные вопросы' — Кодт
Re: SetConsoleCtrlHandler и многопоточность
От: Аноним  
Дата: 18.09.09 09:33
Оценка:
Здравствуйте, mityaj.it.0, Вы писали:

MI0>Привет всем, есть такой код:

MI0>
MI0>BOOL ConsoleHandler( DWORD fdwCtrlType )
MI0>{
MI0>    switch (fdwCtrlType) {
MI0>        case CTRL_C_EVENT: {
MI0>            std::cout << "Exit." << "\n";
MI0>                        exit(1);
MI0>        }

MI0>    }
MI0>}
MI0>int _tmain(int argc, _TCHAR* argv[])
MI0>    if (SetConsoleCtrlHandler( (PHANDLER_ROUTINE)ConsoleHandler,TRUE)==FALSE) {
MI0>        // unable to install handler... 
MI0>        return -1;
MI0>    }
MI0>    try {
MI0>        // Enable exceptions in cin.
MI0>        std::cin.exceptions(std::ios::badbit|std::ios::failbit);
MI0>        int itSum = 0;
MI0>        std::cin >> itSum;
MI0>    catch (...) {
MI0>        std::cout << "Error!" << "\n";
MI0>    }
MI0>}

MI0>

MI0>Необходимо при ожидании ввода числа иметь возможность завершить программу по нажатию [Ctrl+C]. Данный код
MI0>это предоставляет, но с одним "НО": обработчик ConsoleHandler вызывается в другом потоке и основной поток также продолжает выполнение.
MI0>В итоге выполняется обработчик исключения и обработчик [Ctrl+C]. Это некорректно. Каким образом затормозить основной поток или
MI0>дать ему понять, что нажата [Ctrl+C]?

Используйте средства синхронизации, можно посмотреть здесь — http://msdn.microsoft.com/ru-ru/library/172d2hhw.aspx
Re[2]: SetConsoleCtrlHandler и многопоточность
От: mityaj.it.0  
Дата: 18.09.09 11:56
Оценка:
Здравствуйте, Аноним, Вы писали:
А>Используйте средства синхронизации, можно посмотреть здесь — http://msdn.microsoft.com/ru-ru/library/172d2hhw.aspx
Синхронизация мне не поможет. Мне нужно чтобы обработчик исключения мог узнать о событии [Ctrl+C]. А получается так, что он
сначала выполняется, а потом только в другом потоке выполняется обработчик события [Ctrl+C]. Можно создать событие, кот. будет дергать обработчик
события [Ctrl+C] и подождать(где нить 500 мс) его в обработчике исключения, но это уже криво будет.

HANDLE hConsoleEvent = NULL;

int _tmain(int argc, _TCHAR* argv[]) {
...
hConsoleEvent = CreateEvent(NULL, true, false, NULL);
...
catch (...) {
if (WaitForSingleObject(hConsoleEvent, 500) == WAIT_TIMEOUT)
 std::cout << "Error!" << "\n";
else {
// нажали [Ctrl+C]
}
}


BOOL ConsoleHandler( DWORD fdwCtrlType )
{
SetEvent(hConsoleEvent);
...
}
Re[3]: SetConsoleCtrlHandler и многопоточность
От: Сергей Мухин Россия  
Дата: 18.09.09 12:01
Оценка:
Здравствуйте, mityaj.it.0, Вы писали:

MI0>Здравствуйте, Аноним, Вы писали:

А>>Используйте средства синхронизации, можно посмотреть здесь — http://msdn.microsoft.com/ru-ru/library/172d2hhw.aspx
MI0>Синхронизация мне не поможет. Мне нужно чтобы обработчик исключения мог узнать о событии [Ctrl+C]. А получается так, что он
MI0>сначала выполняется, а потом только в другом потоке выполняется обработчик события [Ctrl+C]. Можно создать событие, кот. будет дергать обработчик
MI0>события [Ctrl+C] и подождать(где нить 500 мс) его в обработчике исключения, но это уже криво будет.

Я один раз сделал очень грубо. в Thread захватил контекст главного thread и выставил свой IP.

Это чрезвычайно опасно, но обычно работает
---
С уважением,
Сергей Мухин
Re[4]: SetConsoleCtrlHandler и многопоточность
От: Аноним  
Дата: 19.09.09 11:33
Оценка:
Здравствуйте, Сергей Мухин, Вы писали:
...
СМ>Я один раз сделал очень грубо. в Thread захватил контекст главного thread и выставил свой IP.

СМ>Это чрезвычайно опасно, но обычно работает


Хм... Такой подход должен быть соответственно прокомментирован в коде... Но это не вяжется с вашей подписью =)
Re[5]: SetConsoleCtrlHandler и многопоточность
От: Сергей Мухин Россия  
Дата: 19.09.09 19:34
Оценка:
Здравствуйте, Аноним, Вы писали:

СМ>>Я один раз сделал очень грубо. в Thread захватил контекст главного thread и выставил свой IP.


СМ>>Это чрезвычайно опасно, но обычно работает


А>Хм... Такой подход должен быть соответственно прокомментирован в коде... Но это не вяжется с вашей подписью =)


Что комментировать?
Если написано Context->Eip = myHandler;
Что тут пояснять?
---
С уважением,
Сергей Мухин
Re[6]: SetConsoleCtrlHandler и многопоточность
От: Аноним  
Дата: 20.09.09 05:25
Оценка:
Здравствуйте, Сергей Мухин, Вы писали:

СМ>>>Я один раз сделал очень грубо. в Thread захватил контекст главного thread и выставил свой IP.


СМ>>>Это чрезвычайно опасно, но обычно работает


А>>Хм... Такой подход должен быть соответственно прокомментирован в коде... Но это не вяжется с вашей подписью =)


СМ>Что комментировать?

СМ>Если написано Context->Eip = myHandler;
СМ>Что тут пояснять?

СМ>чрезвычайно опасно, но обычно работает
Re[7]: SetConsoleCtrlHandler и многопоточность
От: Сергей Мухин Россия  
Дата: 20.09.09 18:01
Оценка:
Здравствуйте, Аноним, Вы писали:

СМ>>>>Это чрезвычайно опасно, но обычно работает


А>>>Хм... Такой подход должен быть соответственно прокомментирован в коде... Но это не вяжется с вашей подписью =)


СМ>>Что комментировать?

СМ>>Если написано Context->Eip = myHandler;
СМ>>Что тут пояснять?

чрезвычайно опасно, но обычно работает

1.
гм. Это ОЧЕВИДНО когда написано eip = ...
И зачем. Все равно этот комментарий не раскрывает причин, почему опасно и тп. А причины многочисленные и (на самом деле) довольно редки.
Описывать их все — тяжелая задача. Кстати, на самом деле я делал не только eip, там есть танцы с бубном, что бы повысить устойчивость еще на одну 9

2. это плохая программа, если надо так делать, как все известно, комментарии ее на спасут
---
С уважением,
Сергей Мухин
Re[8]: SetConsoleCtrlHandler и многопоточность
От: Аноним  
Дата: 20.09.09 20:02
Оценка:
Здравствуйте, Сергей Мухин, Вы писали:

СМ>>>Что комментировать?

СМ>>>Если написано Context->Eip = myHandler;
СМ>>>Что тут пояснять?

СМ>чрезвычайно опасно, но обычно работает


СМ>1.

СМ>гм. Это ОЧЕВИДНО когда написано eip = ...
СМ>И зачем. Все равно этот комментарий не раскрывает причин, почему опасно и тп.

Я не до дословно имел ввиду : '//чрезвычайно опасно, но обычно работает', хотя даже это лучше чем ничего.

СМ>А причины многочисленные и (на самом деле) довольно редки.

СМ>Описывать их все — тяжелая задача.

Url/ссылка на книгу/статью... Хотя бы заострить на этом внимание. Пусть бы там было не 'Context->Eip = myHandler', а скажем 'service->reset()'. Да, возможно этот вызов раз в пятилетку приведет к плохому. Мне это так же ОЧЕВИДНО, как и вам про 'eip =', только дело не в этом — там любой код мог бы быть, про который можно сказать "опасно, но обычно работает"


СМ>2. это плохая программа, если надо так делать, как все известно, комментарии ее на спасут

Могут спасти... если все такие места будут помечены хотя бы чем-то вроде '// review' то как минимум их можно очень просто идентифицировать и потом предпринять какие-либо действия по исправлению. Почему их сразу не 'исправили'? А ф.з. причины могут быть разные... старый код с длинной историей и вереницей программистов, необходимость масштабного рефакторинга для исправления пары строк... Я согласен с тем, что лучше бы таких мест не было вообще, но при их наличии мы должны быть заинтересованы в их исправлении.
Re: SetConsoleCtrlHandler и многопоточность
От: Pavel Dvorkin Россия  
Дата: 21.09.09 06:13
Оценка:
Здравствуйте, mityaj.it.0, Вы писали:

MI0>Необходимо при ожидании ввода числа иметь возможность завершить программу по нажатию [Ctrl+C]. Данный код

MI0>это предоставляет, но с одним "НО": обработчик ConsoleHandler вызывается в другом потоке

А нельзя ли объяснить, откуда другой поток взялся. В приведенном коде я его упорно не вижу. При запуске программы (после того, как вставил две недостающие фигурные скобки), Task Manager говорит, что поток один. Откуда дровишки ?
With best regards
Pavel Dvorkin
Re[2]: SetConsoleCtrlHandler и многопоточность
От: Сергей Мухин Россия  
Дата: 21.09.09 06:14
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>Здравствуйте, mityaj.it.0, Вы писали:


MI0>>Необходимо при ожидании ввода числа иметь возможность завершить программу по нажатию [Ctrl+C]. Данный код

MI0>>это предоставляет, но с одним "НО": обработчик ConsoleHandler вызывается в другом потоке

PD>А нельзя ли объяснить, откуда другой поток взялся. В приведенном коде я его упорно не вижу. При запуске программы (после того, как вставил две недостающие фигурные скобки), Task Manager говорит, что поток один. Откуда дровишки ?


Когда управление передается handler'у по Ctrl+Cи тп — он работает на своем новом потоке.
---
С уважением,
Сергей Мухин
Re[9]: SetConsoleCtrlHandler и многопоточность
От: Сергей Мухин Россия  
Дата: 21.09.09 06:15
Оценка:
Здравствуйте, Аноним, Вы писали:


СМ>>1.

СМ>>гм. Это ОЧЕВИДНО когда написано eip = ...
СМ>>И зачем. Все равно этот комментарий не раскрывает причин, почему опасно и тп.

А>Я не до дословно имел ввиду : '//чрезвычайно опасно, но обычно работает', хотя даже это лучше чем ничего.

Вы дословно это написали, пишите что вы хотите сказать, что вы ДУМАЕТЕ понять из сообщение не возможно!

СМ>>А причины многочисленные и (на самом деле) довольно редки.

СМ>>Описывать их все — тяжелая задача.

А>Url/ссылка на книгу/статью... Хотя бы заострить на этом внимание. Пусть бы там было не 'Context->Eip = myHandler', а скажем 'service->reset()'. Да, возможно этот вызов раз в пятилетку приведет к плохому. Мне это так же ОЧЕВИДНО, как и вам про 'eip =', только дело не в этом — там любой код мог бы быть, про который можно сказать "опасно, но обычно работает"


ну вот я на той неделе потратил туеву хучу ввремени что бы найти ошибку в чужой программе. ошибка было (грубо говоря) a[i];
И помогли мне комментарии?

СМ>>2. это плохая программа, если надо так делать, как все известно, комментарии ее на спасут

А>Могут спасти... если все такие места будут помечены хотя бы чем-то вроде '// review' то как минимум их можно очень просто идентифицировать и потом предпринять какие-либо действия по исправлению. Почему их сразу не 'исправили'? А ф.з. причины могут быть разные... старый код с длинной историей и вереницей программистов, необходимость масштабного рефакторинга для исправления пары строк... Я согласен с тем, что лучше бы таких мест не было вообще, но при их наличии мы должны быть заинтересованы в их исправлении.

если все места будут помечены — идеализм.
---
С уважением,
Сергей Мухин
Re[2]: SetConsoleCtrlHandler и многопоточность
От: Pavel Dvorkin Россия  
Дата: 21.09.09 06:21
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>А нельзя ли объяснить, откуда другой поток взялся. В приведенном коде я его упорно не вижу. При запуске программы (после того, как вставил две недостающие фигурные скобки), Task Manager говорит, что поток один. Откуда дровишки ?


Да, проверил, верно, запускается новый поток.
With best regards
Pavel Dvorkin
Re[4]: SetConsoleCtrlHandler и многопоточность
От: mityaj.it.0  
Дата: 21.09.09 07:29
Оценка:
Здравствуйте, Сергей Мухин, Вы писали:

СМ>Здравствуйте, mityaj.it.0, Вы писали:


MI0>>Здравствуйте, Аноним, Вы писали:

А>>>Используйте средства синхронизации, можно посмотреть здесь — http://msdn.microsoft.com/ru-ru/library/172d2hhw.aspx
MI0>>Синхронизация мне не поможет. Мне нужно чтобы обработчик исключения мог узнать о событии [Ctrl+C]. А получается так, что он
MI0>>сначала выполняется, а потом только в другом потоке выполняется обработчик события [Ctrl+C]. Можно создать событие, кот. будет дергать обработчик
MI0>>события [Ctrl+C] и подождать(где нить 500 мс) его в обработчике исключения, но это уже криво будет.

СМ>Я один раз сделал очень грубо. в Thread захватил контекст главного thread и выставил свой IP.

пока я буду в другом потоке выставлять IP, основной поток сделает то, чего мне не надо)
на крайний случай можно перечислить все потоки процесса и если их больше два, то не обрабатывать исключение в моем случае
СМ>Это чрезвычайно опасно, но обычно работает
это реально опасно
Re[5]: SetConsoleCtrlHandler и многопоточность
От: Сергей Мухин Россия  
Дата: 21.09.09 07:33
Оценка:
Здравствуйте, mityaj.it.0, Вы писали:


СМ>>Я один раз сделал очень грубо. в Thread захватил контекст главного thread и выставил свой IP.

MI0>пока я буду в другом потоке выставлять IP, основной поток сделает то, чего мне не надо)

suspendthread

MI0>на крайний случай можно перечислить все потоки процесса и если их больше два, то не обрабатывать исключение в моем случае

на это не стоит закладываться, т.к.
1. завтра ваша программа будет составной частью другой, со многими thread
2. некоторые WindowsAPI ф-ии запускают свои thread, и они не всегда останавливаются по завершению онной

СМ>>Это чрезвычайно опасно, но обычно работает

MI0>это реально опасно

не опасней IsBadReadPtr
---
С уважением,
Сергей Мухин
Re[6]: SetConsoleCtrlHandler и многопоточность
От: mityaj.it.0  
Дата: 21.09.09 07:54
Оценка:
Здравствуйте, Сергей Мухин, Вы писали:

СМ>Здравствуйте, mityaj.it.0, Вы писали:



СМ>>>Я один раз сделал очень грубо. в Thread захватил контекст главного thread и выставил свой IP.

MI0>>пока я буду в другом потоке выставлять IP, основной поток сделает то, чего мне не надо)

СМ>suspendthread

не получится, потому что обработчик события [Ctrl+C] в другом потоке получит управление после обработки исключения в основном потоке(по крайней мере
это нельзя списывать)

MI0>>на крайний случай можно перечислить все потоки процесса и если их больше два, то не обрабатывать исключение в моем случае

СМ>на это не стоит закладываться, т.к.
СМ>1. завтра ваша программа будет составной частью другой, со многими thread
СМ>2. некоторые WindowsAPI ф-ии запускают свои thread, и они не всегда останавливаются по завершению онной
есть такое
Re[7]: SetConsoleCtrlHandler и многопоточность
От: Сергей Мухин Россия  
Дата: 21.09.09 07:59
Оценка:
Здравствуйте, mityaj.it.0, Вы писали:

СМ>>suspendthread

MI0>не получится, потому что обработчик события [Ctrl+C] в другом потоке получит управление после обработки исключения в основном потоке(по крайней мере
MI0>это нельзя списывать)

не понял. Мы сейчас работаем в обработчику Ctrl+C, и пытаемся передать другому thread (например главному) исключение. так?

так как мы получим управление _после_ обработки искл в главном? (т.е. получить то можем, но зачем?)
---
С уважением,
Сергей Мухин
Re[8]: SetConsoleCtrlHandler и многопоточность
От: mityaj.it.0  
Дата: 21.09.09 08:08
Оценка:
Здравствуйте, Сергей Мухин, Вы писали:

СМ>Здравствуйте, mityaj.it.0, Вы писали:


СМ>>>suspendthread

MI0>>не получится, потому что обработчик события [Ctrl+C] в другом потоке получит управление после обработки исключения в основном потоке(по крайней мере
MI0>>это нельзя списывать)

СМ>не понял. Мы сейчас работаем в обработчику Ctrl+C, и пытаемся передать другому thread (например главному) исключение. так?


СМ>так как мы получим управление _после_ обработки искл в главном? (т.е. получить то можем, но зачем?)

Нет.
В главном потоке строка "std::cin >> itSum" ожидает от юзера ввода целого числа, если юзер передумает и захочет выйти,
то он нажмет [Ctrl+C]. В этом случае "std::cin >> itSum" сгенерит исключение(поскольку введено не значение типа int) и винда создаст поток, в кот. передаст управление моему обработчику "ConsoleHandler".
Мне не нужно обрабатывать исключение, поскольку это не ввод числа, а запрос на выход из программы. Вопрос в том, как основному потоку в обработчике исключения понять, что был запрос на выход, а не ввод неверного числа?
Re[9]: SetConsoleCtrlHandler и многопоточность
От: Сергей Мухин Россия  
Дата: 21.09.09 08:27
Оценка:
Здравствуйте, mityaj.it.0, Вы писали:


СМ>>так как мы получим управление _после_ обработки искл в главном? (т.е. получить то можем, но зачем?)

MI0>Нет.
MI0>В главном потоке строка "std::cin >> itSum" ожидает от юзера ввода целого числа, если юзер передумает и захочет выйти,
MI0>то он нажмет [Ctrl+C]. В этом случае "std::cin >> itSum" сгенерит исключение(поскольку введено не значение типа int) и винда создаст поток, в кот. передаст управление моему обработчику "ConsoleHandler".
MI0>Мне не нужно обрабатывать исключение, поскольку это не ввод числа, а запрос на выход из программы. Вопрос в том, как основному потоку в обработчике исключения понять, что был запрос на выход, а не ввод неверного числа?

понятно.
можно сделать так, что Ctrl+C не воспринимался потоком вообще?
не знаю что делать.
---
С уважением,
Сергей Мухин
Re[10]: SetConsoleCtrlHandler и многопоточность
От: Аноним  
Дата: 21.09.09 08:56
Оценка:
Здравствуйте, Сергей Мухин, Вы писали:

СМ>>>гм. Это ОЧЕВИДНО когда написано eip = ...

СМ>>>И зачем. Все равно этот комментарий не раскрывает причин, почему опасно и тп.

А>>Я не до дословно имел ввиду : '//чрезвычайно опасно, но обычно работает', хотя даже это лучше чем ничего.

СМ>Вы дословно это написали, пишите что вы хотите сказать, что вы ДУМАЕТЕ понять из сообщение не возможно!

Я процитировал эту фразу в ответ на вопрос "Что тут пояснять?". Вроде как очевидно что это не является комментарием как таковым, но если не очевидно — это я сам виноват.

А>>Url/ссылка на книгу/статью... Хотя бы заострить на этом внимание. Пусть бы там было не 'Context->Eip = myHandler', а скажем 'service->reset()'. Да, возможно этот вызов раз в пятилетку приведет к плохому. Мне это так же ОЧЕВИДНО, как и вам про 'eip =', только дело не в этом — там любой код мог бы быть, про который можно сказать "опасно, но обычно работает"


СМ>ну вот я на той неделе потратил туеву хучу ввремени что бы найти ошибку в чужой программе. ошибка было (грубо говоря) a[i];

СМ>И помогли мне комментарии?

Возможно я опять неудачно выразился — давайте поделим <некторые> ошибки на две категории: программист уверен что участок кода работает верно, но сам при этом может ошибиться при его написании (т.е. надо 'i >= 0', а он написал 'i > 0') — то ли глаз замылился, то ли отвлекли и т.п., но он уверен что в коде все хорошо. В втором случае программист осознанно выбирает опасный способ реализации — и весьма вероятно, что в этом вероятны обстоятельства (релиз вчера, необходимость масштабного рефакторинга опять же, отсутствие полномочий для принятия решений, и тому подобное). Опасность выбранного случая заключается в том, что даже если он реализован без ошибок — этот код может выстрелить из-за внешних обстоятельств (как Вы сами сказали 'обычно работает').

ошибку в a[i] — я отношу к первой категории (для другого вывода не хватает данных)
'eip =...'/'service->reset()' — это вторая категория.

СМ>>>2. это плохая программа, если надо так делать, как все известно, комментарии ее на спасут

А>>Могут спасти... если все такие места будут помечены хотя бы чем-то вроде '// review' то как минимум их можно очень просто идентифицировать и потом предпринять какие-либо действия по исправлению.

СМ>если все места будут помечены — идеализм.

Стремиться к идеалу и выполнять действия, способствующие в его достижении — это плохо? Такие комментарии реально помогают. По Вашему получается — если программа содержит такой комментарий, то она плохая, комментарии ей не помогут... Такой комменатрий торчит как маяк и говорит "поправь меня". Как по мне, так польза налицо. Иначе можно просто _удалить_ (или не добавлять вообще) этот комментарий — от этого по Вашему программа становится хорошей, хотя "запашок" от такого удаления не исчезает.
Re[11]: SetConsoleCtrlHandler и многопоточность
От: Сергей Мухин Россия  
Дата: 21.09.09 09:02
Оценка:
Здравствуйте, Аноним, Вы писали:


СМ>>>>2. это плохая программа, если надо так делать, как все известно, комментарии ее на спасут

А>>>Могут спасти... если все такие места будут помечены хотя бы чем-то вроде '// review' то как минимум их можно очень просто идентифицировать и потом предпринять какие-либо действия по исправлению.

СМ>>если все места будут помечены — идеализм.

А>Стремиться к идеалу и выполнять действия, способствующие в его достижении — это плохо? Такие комментарии реально помогают.

??? реально помочь — это исправить. Комментари этого сделать не могут по определению.
Они могут обозначить проблемную точку, но и только, Это создает ложное заключение, что мы знаем сложные места. А ломается обычно не там


По Вашему получается — если программа содержит такой комментарий, то она плохая, комментарии ей не помогут... Такой комменатрий торчит как маяк и говорит "поправь меня". Как по мне, так польза налицо. Иначе можно просто _удалить_ (или не добавлять вообще) этот комментарий — от этого по Вашему программа становится хорошей, хотя "запашок" от такого удаления не исчезает.

я никогда не говорил, что если есть комментарии, то программа плохая! "Хорошесть" определяется только кодом.
---
С уважением,
Сергей Мухин
Re: SetConsoleCtrlHandler и многопоточность
От: gear nuke  
Дата: 21.09.09 16:17
Оценка:
Здравствуйте, mityaj.it.0, Вы писали:

MI0>Каким образом затормозить основной поток или

MI0>дать ему понять, что нажата [Ctrl+C]?

Если рабочий тред всего один, возможно так:
bool ctrl_c = false;

BOOL ConsoleHandler( DWORD fdwCtrlType )
{
    switch (fdwCtrlType) {
        case CTRL_C_EVENT: {
            ctrl_c = true;
            std::cout << "Exit." << "\n";
            exit(1);
        }
    }
}
int main(){

    // Гарантируем выполнение только одного треда в единицу времени
    SetProcessAffinityMask(GetCurrentProcess(), 1);
    
    if (SetConsoleCtrlHandler( (PHANDLER_ROUTINE)ConsoleHandler,TRUE)==FALSE) {
        // unable to install handler... 
        return -1;
    }
    try {
        // Enable exceptions in cin.
        std::cin.exceptions(std::ios::failbit);
        int itSum = 0;
        std::cin >> itSum;
    }
    catch (...) {
    
        // Принудительно выполняем тред с ConsoleHandler
        SwitchToThread();
        
        if ( ! ctrl_c ) 
          std::cout << "Error!" << "\n";
    }

}

Можно еще попробовать GetKeyState(VK_CONTROL);
.
People who are more than casually interested in computers should have at least some idea of what the underlying hardware is like. Otherwise the programs they write will be pretty weird (c) D.Knuth
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.