Необходимо при ожидании ввода числа иметь возможность завершить программу по нажатию [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>Необходимо при ожидании ввода числа иметь возможность завершить программу по нажатию [Ctrl+C]. Данный код MI0>это предоставляет, но с одним "НО": обработчик ConsoleHandler вызывается в другом потоке и основной поток также продолжает выполнение. MI0>В итоге выполняется обработчик исключения и обработчик [Ctrl+C]. Это некорректно. Каким образом затормозить основной поток или MI0>дать ему понять, что нажата [Ctrl+C]?
Здравствуйте, Аноним, Вы писали: А>Используйте средства синхронизации, можно посмотреть здесь — http://msdn.microsoft.com/ru-ru/library/172d2hhw.aspx
Синхронизация мне не поможет. Мне нужно чтобы обработчик исключения мог узнать о событии [Ctrl+C]. А получается так, что он
сначала выполняется, а потом только в другом потоке выполняется обработчик события [Ctrl+C]. Можно создать событие, кот. будет дергать обработчик
события [Ctrl+C] и подождать(где нить 500 мс) его в обработчике исключения, но это уже криво будет.
Здравствуйте, 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.
СМ>Это чрезвычайно опасно, но обычно работает
Хм... Такой подход должен быть соответственно прокомментирован в коде... Но это не вяжется с вашей подписью =)
Здравствуйте, Аноним, Вы писали:
СМ>>Я один раз сделал очень грубо. в Thread захватил контекст главного thread и выставил свой IP.
СМ>>Это чрезвычайно опасно, но обычно работает
А>Хм... Такой подход должен быть соответственно прокомментирован в коде... Но это не вяжется с вашей подписью =)
Что комментировать?
Если написано Context->Eip = myHandler;
Что тут пояснять?
---
С уважением,
Сергей Мухин
Re[6]: SetConsoleCtrlHandler и многопоточность
От:
Аноним
Дата:
20.09.09 05:25
Оценка:
Здравствуйте, Сергей Мухин, Вы писали:
СМ>>>Я один раз сделал очень грубо. в Thread захватил контекст главного thread и выставил свой IP.
СМ>>>Это чрезвычайно опасно, но обычно работает
А>>Хм... Такой подход должен быть соответственно прокомментирован в коде... Но это не вяжется с вашей подписью =)
СМ>Что комментировать? СМ>Если написано Context->Eip = myHandler; СМ>Что тут пояснять?
СМ>чрезвычайно опасно, но обычно работает
Здравствуйте, Аноним, Вы писали:
СМ>>>>Это чрезвычайно опасно, но обычно работает
А>>>Хм... Такой подход должен быть соответственно прокомментирован в коде... Но это не вяжется с вашей подписью =)
СМ>>Что комментировать? СМ>>Если написано 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' то как минимум их можно очень просто идентифицировать и потом предпринять какие-либо действия по исправлению. Почему их сразу не 'исправили'? А ф.з. причины могут быть разные... старый код с длинной историей и вереницей программистов, необходимость масштабного рефакторинга для исправления пары строк... Я согласен с тем, что лучше бы таких мест не было вообще, но при их наличии мы должны быть заинтересованы в их исправлении.
Здравствуйте, mityaj.it.0, Вы писали:
MI0>Необходимо при ожидании ввода числа иметь возможность завершить программу по нажатию [Ctrl+C]. Данный код MI0>это предоставляет, но с одним "НО": обработчик ConsoleHandler вызывается в другом потоке
А нельзя ли объяснить, откуда другой поток взялся. В приведенном коде я его упорно не вижу. При запуске программы (после того, как вставил две недостающие фигурные скобки), Task Manager говорит, что поток один. Откуда дровишки ?
Здравствуйте, Pavel Dvorkin, Вы писали:
PD>Здравствуйте, mityaj.it.0, Вы писали:
MI0>>Необходимо при ожидании ввода числа иметь возможность завершить программу по нажатию [Ctrl+C]. Данный код MI0>>это предоставляет, но с одним "НО": обработчик ConsoleHandler вызывается в другом потоке
PD>А нельзя ли объяснить, откуда другой поток взялся. В приведенном коде я его упорно не вижу. При запуске программы (после того, как вставил две недостающие фигурные скобки), Task Manager говорит, что поток один. Откуда дровишки ?
Когда управление передается handler'у по Ctrl+Cи тп — он работает на своем новом потоке.
СМ>>1. СМ>>гм. Это ОЧЕВИДНО когда написано eip = ... СМ>>И зачем. Все равно этот комментарий не раскрывает причин, почему опасно и тп.
А>Я не до дословно имел ввиду : '//чрезвычайно опасно, но обычно работает', хотя даже это лучше чем ничего.
Вы дословно это написали, пишите что вы хотите сказать, что вы ДУМАЕТЕ понять из сообщение не возможно!
СМ>>А причины многочисленные и (на самом деле) довольно редки. СМ>>Описывать их все — тяжелая задача.
А>Url/ссылка на книгу/статью... Хотя бы заострить на этом внимание. Пусть бы там было не 'Context->Eip = myHandler', а скажем 'service->reset()'. Да, возможно этот вызов раз в пятилетку приведет к плохому. Мне это так же ОЧЕВИДНО, как и вам про 'eip =', только дело не в этом — там любой код мог бы быть, про который можно сказать "опасно, но обычно работает"
ну вот я на той неделе потратил туеву хучу ввремени что бы найти ошибку в чужой программе. ошибка было (грубо говоря) a[i];
И помогли мне комментарии?
СМ>>2. это плохая программа, если надо так делать, как все известно, комментарии ее на спасут А>Могут спасти... если все такие места будут помечены хотя бы чем-то вроде '// review' то как минимум их можно очень просто идентифицировать и потом предпринять какие-либо действия по исправлению. Почему их сразу не 'исправили'? А ф.з. причины могут быть разные... старый код с длинной историей и вереницей программистов, необходимость масштабного рефакторинга для исправления пары строк... Я согласен с тем, что лучше бы таких мест не было вообще, но при их наличии мы должны быть заинтересованы в их исправлении.
Здравствуйте, Pavel Dvorkin, Вы писали:
PD>А нельзя ли объяснить, откуда другой поток взялся. В приведенном коде я его упорно не вижу. При запуске программы (после того, как вставил две недостающие фигурные скобки), Task Manager говорит, что поток один. Откуда дровишки ?
Здравствуйте, Сергей Мухин, Вы писали:
СМ>Здравствуйте, 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, основной поток сделает то, чего мне не надо)
на крайний случай можно перечислить все потоки процесса и если их больше два, то не обрабатывать исключение в моем случае СМ>Это чрезвычайно опасно, но обычно работает
это реально опасно
СМ>>Я один раз сделал очень грубо. в Thread захватил контекст главного thread и выставил свой IP. MI0>пока я буду в другом потоке выставлять IP, основной поток сделает то, чего мне не надо)
suspendthread
MI0>на крайний случай можно перечислить все потоки процесса и если их больше два, то не обрабатывать исключение в моем случае
на это не стоит закладываться, т.к.
1. завтра ваша программа будет составной частью другой, со многими thread
2. некоторые WindowsAPI ф-ии запускают свои thread, и они не всегда останавливаются по завершению онной
СМ>>Это чрезвычайно опасно, но обычно работает MI0>это реально опасно
Здравствуйте, Сергей Мухин, Вы писали:
СМ>Здравствуйте, mityaj.it.0, Вы писали:
СМ>>>Я один раз сделал очень грубо. в Thread захватил контекст главного thread и выставил свой IP. MI0>>пока я буду в другом потоке выставлять IP, основной поток сделает то, чего мне не надо)
СМ>suspendthread
не получится, потому что обработчик события [Ctrl+C] в другом потоке получит управление после обработки исключения в основном потоке(по крайней мере
это нельзя списывать)
MI0>>на крайний случай можно перечислить все потоки процесса и если их больше два, то не обрабатывать исключение в моем случае СМ>на это не стоит закладываться, т.к. СМ>1. завтра ваша программа будет составной частью другой, со многими thread СМ>2. некоторые WindowsAPI ф-ии запускают свои thread, и они не всегда останавливаются по завершению онной
есть такое
Здравствуйте, mityaj.it.0, Вы писали:
СМ>>suspendthread MI0>не получится, потому что обработчик события [Ctrl+C] в другом потоке получит управление после обработки исключения в основном потоке(по крайней мере MI0>это нельзя списывать)
не понял. Мы сейчас работаем в обработчику Ctrl+C, и пытаемся передать другому thread (например главному) исключение. так?
так как мы получим управление _после_ обработки искл в главном? (т.е. получить то можем, но зачем?)
Здравствуйте, Сергей Мухин, Вы писали:
СМ>Здравствуйте, mityaj.it.0, Вы писали:
СМ>>>suspendthread MI0>>не получится, потому что обработчик события [Ctrl+C] в другом потоке получит управление после обработки исключения в основном потоке(по крайней мере MI0>>это нельзя списывать)
СМ>не понял. Мы сейчас работаем в обработчику Ctrl+C, и пытаемся передать другому thread (например главному) исключение. так?
СМ>так как мы получим управление _после_ обработки искл в главном? (т.е. получить то можем, но зачем?)
Нет.
В главном потоке строка "std::cin >> itSum" ожидает от юзера ввода целого числа, если юзер передумает и захочет выйти,
то он нажмет [Ctrl+C]. В этом случае "std::cin >> itSum" сгенерит исключение(поскольку введено не значение типа int) и винда создаст поток, в кот. передаст управление моему обработчику "ConsoleHandler".
Мне не нужно обрабатывать исключение, поскольку это не ввод числа, а запрос на выход из программы. Вопрос в том, как основному потоку в обработчике исключения понять, что был запрос на выход, а не ввод неверного числа?
СМ>>так как мы получим управление _после_ обработки искл в главном? (т.е. получить то можем, но зачем?) 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' то как минимум их можно очень просто идентифицировать и потом предпринять какие-либо действия по исправлению.
СМ>если все места будут помечены — идеализм.
Стремиться к идеалу и выполнять действия, способствующие в его достижении — это плохо? Такие комментарии реально помогают. По Вашему получается — если программа содержит такой комментарий, то она плохая, комментарии ей не помогут... Такой комменатрий торчит как маяк и говорит "поправь меня". Как по мне, так польза налицо. Иначе можно просто _удалить_ (или не добавлять вообще) этот комментарий — от этого по Вашему программа становится хорошей, хотя "запашок" от такого удаления не исчезает.