Здравствуйте, Sergey, Вы писали:
>> S>Интересно, а join тут у вас обсуждается бустовый или какой-то другой? Просто boost::thread::join() под виндой никого не убивает, а ждет завершения потока. Та же ситуация, которую вы описали, равнозначна вызову виндовой TerminаteThread и в общем не должна возникать при отсутствии в программе фатальных ошибок. Не знаю, как под другими операционками, но под виндой так завершать нити не следует. >> >> Может недописано всё? >> У меня в доморошенном потоке в joine стоит некое разумное время завершения, после чего прога поток заверщает и ругается на мои кривые руки правда это токо в дебаг режиме ...
S>Чего не дописано? Под виндой нет ни одного безопасного способа остановить нить извне. Потому что никто не гарантирует, что при вызове той же TerminateThread операционка озаботится отпусканием захваченных этой нитью объектов синхронизации или выполнит еще какие-либо post mortem действия в контексте прерванной нити. Так что все там сделано правильно.
Да никто и не говорит, что сделано неправильно.
Меня не поняли
Я просто сказал, что там может быть неполный код, вот и все.
Насчет пост действий я тоже согласен, кроме объектов синхронизаций. Для некоторых (а конкретно для mutex-а) Windows гарантирует передачу ownership к одному из ожидающих объектов. Другой вопрос — а что же там в shared данных творится, но он выходит за пределы обсуждаемой темы
> PPL! читаем внимательно: все мои листинги в этом топике ПСЕВДОКОД таких вызовов и классов не существует! -- всем расслабица...
Т.е., мы обсуждаем код, который не может быть реализован?
> ЗЫ: я и вправду немного ступил насчет join'a -- конечно же он не убивает thread... чтобы эстетам стало легче вообразите перед вызовом join'a такой псевдокод:
> ...
> thr.cancel(); // say 'DIE' to thread...
> thr.join(); // wait for thread death...
> ...
>
Как именно реализован cancel? Под виндой, естественно. И почему именно не будет вызван деструктор obj?
Posted via RSDN NNTP Server 2.0
Одним из 33 полных кавалеров ордена "За заслуги перед Отечеством" является Геннадий Хазанов.
Здравствуйте, Sergey, Вы писали:
>> PPL! читаем внимательно: все мои листинги в этом топике ПСЕВДОКОД таких вызовов и классов не существует! -- всем расслабица...
S>Т.е., мы обсуждаем код, который не может быть реализован?
отчего же не может? но в рамках данного топика ДА -- этот код не существует... может быть пока аффтар топика его не напишет
>> ЗЫ: я и вправду немного ступил насчет join'a -- конечно же он не убивает thread... чтобы эстетам стало легче вообразите перед вызовом join'a такой псевдокод:
>> ...
>> thr.cancel(); // say 'DIE' to thread...
>> thr.join(); // wait for thread death...
>> ...
>>
S>Как именно реализован cancel? Под виндой, естественно. И почему именно не будет вызван деструктор obj?
давайте не буим скатываться до уровня операционок -- до сих пор мы поговорили об обобщенном подходе многих известных ОС к убийству threadов...
и общая картина такова: большенству реализаций threadов накласть на то что происходит в убиваемом thread'e как только специальным API (TerminateThread/pthread_cancel/smth_else) запрошено убить когото -- тот умираит безвозвратно и все что было создано в контексте убитого thread'a превращается в leak...
вот так в целом обстоит дело...
поэтому если писать тупые врапперы скрывающие от их пользователя 1 параметр (thread id в том или ином виде) и подменяющие его "объектом" thread -- это не упрощает нелегкое дело написания multithreadных прог... какбы комуто наивно не казалось...
мы тут попытались обсудить с какими проблемами придется столкнуться аффтору топика еси он хочет иметь не просто врапперы а нечто более интеллектуальное и призванное устранить некоторые известные проблемы в этой области... (точнее я пытался его на это подбить )
> Насчет пост действий я тоже согласен, кроме объектов синхронизаций. Для некоторых (а конкретно для mutex-а) Windows гарантирует передачу ownership к одному из ожидающих объектов.
Ни разу не встречал такой информации. Можно ссылку на источник? Хотя я имел в виду не мьютексы, а критические секции — "If the target thread owns a critical section, the critical section will not be released." Это из MSDN, из ремарок про TerminateThread. Еще там есть "If the target thread is allocating memory from the heap, the heap lock will not be released."
Posted via RSDN NNTP Server 2.0
Одним из 33 полных кавалеров ордена "За заслуги перед Отечеством" является Геннадий Хазанов.
>>> PPL! читаем внимательно: все мои листинги в этом топике ПСЕВДОКОД таких вызовов и классов не существует! -- всем расслабица... > > S>Т.е., мы обсуждаем код, который не может быть реализован? > > отчего же не может?
Оттого, что под виндой данный код не может быть реализован (корректно реализован, естественно) в виду отсутствия гарантий операционной системы.
>>> ЗЫ: я и вправду немного ступил насчет join'a -- конечно же он не убивает thread... чтобы эстетам стало легче вообразите перед вызовом join'a такой псевдокод:
>>> ...
>>> thr.cancel(); // say 'DIE' to thread...
>>> thr.join(); // wait for thread death...
>>> ...
>>>
> > S>Как именно реализован cancel? Под виндой, естественно. И почему именно не будет вызван деструктор obj? > > давайте не буим скатываться до уровня операционок -- до сих пор мы поговорили об обобщенном подходе многих известных ОС к убийству threadов...
А давайте буим? Потому что конкретно под виндой ваш подход не работает.
> > и общая картина такова: большенству реализаций threadов накласть на то что происходит в убиваемом thread'e как только специальным API (TerminateThread/pthread_cancel/smth_else) запрошено убить когото -- тот умираит безвозвратно и все что было создано в контексте убитого thread'a превращается в leak...
Еще раз повторяю — вменяемые программисты используют TerminateThread очень осторожно. Ну а pthread_cancel подразумевает вызов cleanup handler'ов, что при желании позволяет организовать "закат солнца вручную". Это, кстати, принципиальная разница, которая как раз заставляет "скатываться до уровня операционок". И, между прочим, написание врапперов неплохо помогает эти самых хэндлеры регистрировать.
> > вот так в целом обстоит дело... > поэтому если писать тупые врапперы скрывающие от их пользователя 1 параметр (thread id в том или ином виде) и подменяющие его "объектом" thread -- это не упрощает нелегкое дело написания multithreadных прог... какбы комуто наивно не казалось...
Если нитку приходится ждать, то враппер очень даже полезен — хотя бы для того, чтобы не забыть закрыть ее хэндл. Ну а насчет void* в качестве параметра — это, конечно, худший вариант, гораздо приятнее работать с интерфейсом в стиле boost::thread.
> > мы тут попытались обсудить с какими проблемами придется столкнуться аффтору топика еси он хочет иметь не просто врапперы а нечто более интеллектуальное и призванное устранить некоторые известные проблемы в этой области... (точнее я пытался его на это подбить )
Если автор топика будет использовать TerminateThread, проблемы у него, безусловно, будут
Posted via RSDN NNTP Server 2.0
Одним из 33 полных кавалеров ордена "За заслуги перед Отечеством" является Геннадий Хазанов.
Здравствуйте, Sergey, Вы писали:
>>>> PPL! читаем внимательно: все мои листинги в этом топике ПСЕВДОКОД таких вызовов и классов не существует! -- всем расслабица... >> >> S>Т.е., мы обсуждаем код, который не может быть реализован? >> >> отчего же не может?
S>Оттого, что под виндой данный код не может быть реализован (корректно реализован, естественно) в виду отсутствия гарантий операционной системы.
о каких гарантях речь?
---
раз ОС ничего не гарантирует может надо написать код (реализацию threads with C++ support) который буит чтото гарантировать? -- просто надо подумать а не уповать на корявую ОС... моск программеру для этого и дан
>>>> ЗЫ: я и вправду немного ступил насчет join'a -- конечно же он не убивает thread... чтобы эстетам стало легче вообразите перед вызовом join'a такой псевдокод:
>>>> ...
>>>> thr.cancel(); // say 'DIE' to thread...
>>>> thr.join(); // wait for thread death...
>>>> ...
>>>>
>> >> S>Как именно реализован cancel? Под виндой, естественно. И почему именно не будет вызван деструктор obj? >> >> давайте не буим скатываться до уровня операционок -- до сих пор мы поговорили об обобщенном подходе многих известных ОС к убийству threadов...
S>А давайте буим? Потому что конкретно под виндой ваш подход не работает.
я еще ничего не говорил о "моем подходе"... все что я сказал было о том как здорово былоб иметь вот такой код и ничего о том как этого добиться (я таки хотел аффтара подбить на размышления об этом)
>> >> и общая картина такова: большенству реализаций threadов накласть на то что происходит в убиваемом thread'e как только специальным API (TerminateThread/pthread_cancel/smth_else) запрошено убить когото -- тот умираит безвозвратно и все что было создано в контексте убитого thread'a превращается в leak...
S>Еще раз повторяю — вменяемые программисты используют TerminateThread очень осторожно. Ну а pthread_cancel подразумевает вызов cleanup handler'ов, что при желании позволяет организовать "закат солнца вручную". Это, кстати, принципиальная разница, которая как раз заставляет "скатываться до уровня операционок". И, между прочим, написание врапперов неплохо помогает эти самых хэндлеры регистрировать.
Ох не надо самовнушать себе что cleanup handlerы решают все проблемы мира! подобный закат солнца далеко не простая процедура... и организовать с их помошью то что делает компилятор когда переменная выходит из области видимости не простая задача (а с ростом локальных переменных с нетривиальным удалением она превращаяется в АЦЦКУЮ )
кстати в "моем подходе" никакие cleanup handlerы НЕ НУЖНЫ... что делает TerminateThread и pthread_cancel принципиально одинаковыми!
>> вот так в целом обстоит дело... >> поэтому если писать тупые врапперы скрывающие от их пользователя 1 параметр (thread id в том или ином виде) и подменяющие его "объектом" thread -- это не упрощает нелегкое дело написания multithreadных прог... какбы комуто наивно не казалось...
S>Если нитку приходится ждать, то враппер очень даже полезен — хотя бы для того, чтобы не забыть закрыть ее хэндл. Ну а насчет void* в качестве параметра — это, конечно, худший вариант, гораздо приятнее работать с интерфейсом в стиле boost::thread.
никто не спорит что врапперы полезны... но зачем ограничивать себя всего лишь врапперами если можно сделать все гараздо кашернее?
вот основная идея топика
>> >> мы тут попытались обсудить с какими проблемами придется столкнуться аффтору топика еси он хочет иметь не просто врапперы а нечто более интеллектуальное и призванное устранить некоторые известные проблемы в этой области... (точнее я пытался его на это подбить )
S>Если автор топика будет использовать TerminateThread, проблемы у него, безусловно, будут
но их можно решить! заимплементив то о чем я говорил... и не нада еще раз повторять про вменяемых программеров и TerminateThread
> раз ОС ничего не гарантирует может надо написать код (реализацию threads with C++ support) который буит чтото гарантировать? -- просто надо подумать а не уповать на корявую ОС... моск программеру для этого и дан
Напиши, если моск позволяет Только учти, что для более-менее полноценной реализации cancel handler'ов драйвер писать придется (или использовать чужой, типа alertdrv.sys). Для не очень полноценной — использовать хак типа вызова на SetThreadContext.
> S>А давайте буим? Потому что конкретно под виндой ваш подход не работает. > > я еще ничего не говорил о "моем подходе"... все что я сказал было о том как здорово былоб иметь вот такой код и ничего о том как этого добиться (я таки хотел аффтара подбить на размышления об этом)
Тогда почему бы не продолжить маниловщину — как здорово было б, чтоб такой код еще и деструкторы вызывал? Кстати, реализация pthread_cancel, основанная на SetThreadContext, вполне может и деструкторы вызывать. Только это все равно всех проблем не решает.
> Ох не надо самовнушать себе что cleanup handlerы решают все проблемы мира! подобный закат солнца далеко не простая процедура... и организовать с их помошью то что делает компилятор когда переменная выходит из области видимости не простая задача (а с ростом локальных переменных с нетривиальным удалением она превращаяется в АЦЦКУЮ ) > > кстати в "моем подходе" никакие cleanup handlerы НЕ НУЖНЫ... что делает TerminateThread и pthread_cancel принципиально одинаковыми!
А кто мьютексы/критические секции отпускать будет? В том числе, залоченные операционкой?
> никто не спорит что врапперы полезны... но зачем ограничивать себя всего лишь врапперами если можно сделать все гараздо кашернее?
Самый кошерный способ — завершать нитку "добровольно", поднимая из контекста другой нити флаг, который терминируемая нить достаточно часто проверяет. А вовсе не игры с RaiseException в стиле виндовой реализации pthreads.
> S>Если автор топика будет использовать TerminateThread, проблемы у него, безусловно, будут > > но их можно решить!
Их можно просто не иметь, в большинстве случаев
> заимплементив то о чем я говорил... и не нада еще раз повторять про вменяемых программеров и TerminateThread
Ну если заняться больше нечем — то почему бы и нет.
Posted via RSDN NNTP Server 2.0
Одним из 33 полных кавалеров ордена "За заслуги перед Отечеством" является Геннадий Хазанов.
Здравствуйте, Sergey, Вы писали:
>> раз ОС ничего не гарантирует может надо написать код (реализацию threads with C++ support) который буит чтото гарантировать? -- просто надо подумать а не уповать на корявую ОС... моск программеру для этого и дан
S>Напиши, если моск позволяет Только учти, что для более-менее полноценной реализации cancel handler'ов драйвер писать придется (или использовать чужой, типа alertdrv.sys). Для не очень полноценной — использовать хак типа вызова на SetThreadContext.
уже! года 3 назад
обошлось без описаных тобой ужасов...
S>А кто мьютексы/критические секции отпускать будет? В том числе, залоченные операционкой?
>> никто не спорит что врапперы полезны... но зачем ограничивать себя всего лишь врапперами если можно сделать все гараздо кашернее?
S>Самый кошерный способ — завершать нитку "добровольно", поднимая из контекста другой нити флаг, который терминируемая нить достаточно часто проверяет. А вовсе не игры с RaiseException в стиле виндовой реализации pthreads.
верной дорогой идете товарисч!
>> S>Если автор топика будет использовать TerminateThread, проблемы у него, безусловно, будут >> >> но их можно решить!
S>Их можно просто не иметь, в большинстве случаев
тоже хороший подход -- но не всегда срабатывает...
>> заимплементив то о чем я говорил... и не нада еще раз повторять про вменяемых программеров и TerminateThread
S>Ну если заняться больше нечем — то почему бы и нет.
в том то и дело что есть чем заняться кроме изобретения велосипедов -- поэтому лучше один раз сесть и написать себе библу чем заниматься постоянным написанием новых решений дурацкой проблемы...
> S>Напиши, если моск позволяет Только учти, что для более-менее полноценной реализации cancel handler'ов драйвер писать придется (или использовать чужой, типа alertdrv.sys). Для не очень полноценной — использовать хак типа вызова на SetThreadContext. > > уже! года 3 назад > обошлось без описаных тобой ужасов...
Под винду? Можно поинтересоваться, как реализовано убивание нити?
Posted via RSDN NNTP Server 2.0
Одним из 33 полных кавалеров ордена "За заслуги перед Отечеством" является Геннадий Хазанов.
Здравствуйте, Sergey, Вы писали:
>> S>Напиши, если моск позволяет Только учти, что для более-менее полноценной реализации cancel handler'ов драйвер писать придется (или использовать чужой, типа alertdrv.sys). Для не очень полноценной — использовать хак типа вызова на SetThreadContext. >> >> уже! года 3 назад >> обошлось без описаных тобой ужасов...
S>Под винду? Можно поинтересоваться, как реализовано убивание нити?
нет я с виндой завязал 6 лет назад
сделал максимально кроссплатформенно... разумеется есть system depended code и виндовая часть все еще ожидает своего аффтара
Основная идея в том, что нить не убивается системными средствами, а сама покидает этот мир
Конечно же у нее есть средства чтоб понять этот момент: вылетающий thread_cancel exception внутри thread'a одно из них, и самое действенное. И программер как существо разумное стремиться обезопасить себя от ликов и прочих неприятностей связаных со "смертью" thread'a используя при этом нативные С++ные средства (большенство из которых имплементит за него компилятор -- как то: вызов деструкторов)
Здравствуйте, Sergey, Вы писали:
>> Насчет пост действий я тоже согласен, кроме объектов синхронизаций. Для некоторых (а конкретно для mutex-а) Windows гарантирует передачу ownership к одному из ожидающих объектов.
S>Ни разу не встречал такой информации. Можно ссылку на источник? Хотя я имел в виду не мьютексы, а критические секции — "If the target thread owns a critical section, the critical section will not be released." Это из MSDN, из ремарок про TerminateThread. Еще там есть "If the target thread is allocating memory from the heap, the heap lock will not be released."
А вот что говорит MSDN о мутексах
"Mutex Objects". Ищется в индексе. Предпоследний абзац снизу
If a thread terminates without releasing its ownership of a mutex object, the mutex object is considered to be abandoned. A waiting thread can acquire ownership of an abandoned mutex object, but the wait function will return WAIT_ABANDONED to indicate that the mutex object is abandoned. An abandoned mutex object indicates that an error has occurred and that any shared resource being protected by the mutex object is in an undefined state.
Здравствуйте, zaufi, Вы писали:
Z>Основная идея в том, что нить не убивается системными средствами, а сама покидает этот мир Z>Конечно же у нее есть средства чтоб понять этот момент: вылетающий thread_cancel exception внутри thread'a одно из них, и самое действенное. И программер как существо разумное стремиться обезопасить себя от ликов и прочих неприятностей связаных со "смертью" thread'a используя при этом нативные С++ные средства (большенство из которых имплементит за него компилятор -- как то: вызов деструкторов)
Интересно ...
Но тогда наверно при програмировании такого "волшебного" треда нужно помнить, что надолго зависать нельзя и постоянно отчитыватся глобальному судье — "а вот он я.. не завис", а судья тады милостиво будет разрешать тебе работать дальше (или не разрешать)
Или ошибаюсь?
Здравствуйте, Kapone, Вы писали:
K>Здравствуйте, zaufi, Вы писали:
Z>>Основная идея в том, что нить не убивается системными средствами, а сама покидает этот мир Z>>Конечно же у нее есть средства чтоб понять этот момент: вылетающий thread_cancel exception внутри thread'a одно из них, и самое действенное. И программер как существо разумное стремиться обезопасить себя от ликов и прочих неприятностей связаных со "смертью" thread'a используя при этом нативные С++ные средства (большенство из которых имплементит за него компилятор -- как то: вызов деструкторов)
K>Интересно ... K>Но тогда наверно при програмировании такого "волшебного" треда нужно помнить, что надолго зависать нельзя и постоянно отчитыватся глобальному судье — "а вот он я.. не завис", а судья тады милостиво будет разрешать тебе работать дальше (или не разрешать) K>Или ошибаюсь?
да разумееца надолго зависать не хорошо... но отчитываться тоже ни перед кем не надо
нужно всего лишь быть готовым обработать исключение thread_cancel и самозавершиться в случае его поимки
хотя бывают моменты когда самаму приходится узнавать нужен ты комуто еще или нет -- для этого есть is_canceled() возвращающая true если ктото желает смерти текущему thread'у
Здравствуйте, zaufi, Вы писали:
Z>да разумееца надолго зависать не хорошо... но отчитываться тоже ни перед кем не надо Z>нужно всего лишь быть готовым обработать исключение thread_cancel и самозавершиться в случае его поимки Z>хотя бывают моменты когда самаму приходится узнавать нужен ты комуто еще или нет -- для этого есть is_canceled() возвращающая true если ктото желает смерти текущему thread'у
Наверно ты не так меня понял
Я имел ввиду, что все равно поток ДОЛЖЕН знать, что когда нибудь его кто-то захочет закенселить. Исходя из этого он постоянно (на там по ходу цикла наприер) вызывает ф-цию, которая может выбросить исключение.
Это ведет к уже указанному мной колбеку.
Подумав над проблемой глобально (то есть от нечего делать в эл-ке), я выделил для себя 3 момента, могущих заставить поток зависнуть всерьез и надолго. В конкретных случаях для всех этих случаев можно заранее придумать заготовки и аккуратно програмировать, напоминая себе постояно "Меня могут попросить свалить.Меня могут попросить свалить....."
Вот какие случаи и выходы из них я выделил бы:
Какой нить длииииииинный цикл, чего делающий
Решение.
аналог пресловутого is_canceled(). Но я бы назвал его MyMegaThread::CheckCancelFlag(). И вставлять его можно в некритичном месте затяжного цикла, но достаточно часто вызываемом для быстрой реакции на команды свали .. тьху, то есть, cancel
Ожидание какого нить события (ну там в очередь пришли данные или еще чего). В этом обычно учавствуют ф-ции Wait... для Винды или select тд для Уникс
Решение.
Замена этих ф-ций на свои MyMegaThread::WaitForSingleObject() и MyMegaThread::WaitForMultiplyObjects()
Если кто до сих пор не разгадал приема, поясню.
На самом деле они все вызывают WaitForMultipleObjects c неким скрытым ивентом, который есть членом этого самого threada.
Детали неясны (это же ведь только проект), но с ними можно определится в конкретной ситуации.
Эта ф-ция тоже может бросить thread_canceled_exception, если сработает этот самый ивент
Блокирующий вызова в ядро (различного рода read, write и тд)
Решение.
Это самый сложный случай из всех. И наверно именно из-за него советовали писать драйвер и другие подобные страхи (или покупать). Конечно, преимущество драйвера неоспоримо, ведь тогда он берет на себя работу по отслеживанию текущих блокировок и их корректному завершению, но тогда мы становимся его заложниками. Для большой системы это еще приемлемо, но не маленьких это неприемлемо.
Ну голь на выдумки емка, так что можно всего лишь обойтись локальным хранилищем хендлов. Разумеется, чтобы все это дело автоматизировать, придётся писать фремворк, в котором необходимо завести базовый класс HandleBase, в котором и будет проходить вся работа по помещению хендла в таблицу возможно зависших хендлов MegaThreada.
Многие скажут, что это гемор и всё такое, но на самом деле — не такой уж и гемор.
Ведь есть всего несколько видов блокирующих хендлов — File, Socket, Pipe. Но всё равно всё сходится к файлам, к ним родимым.
А для них всегда есть CancelIo или CloseHandle или в HandleBase можно определить виртуальную Cancel(), которая будет зависет от конкретного файлового дескриптора.
Для общего же случая с "тупой" ОС боротся не получится и придется либо убивать поток лопатой(то есть Terminate), либо, засучив рукава, решать каждый конкретный случай отдельно.
> Z>да разумееца надолго зависать не хорошо... но отчитываться тоже ни перед кем не надо > Z>нужно всего лишь быть готовым обработать исключение thread_cancel и самозавершиться в случае его поимки > Z>хотя бывают моменты когда самаму приходится узнавать нужен ты комуто еще или нет -- для этого есть is_canceled() возвращающая true если ктото желает смерти текущему thread'у > > Наверно ты не так меня понял > Я имел ввиду, что все равно поток ДОЛЖЕН знать, что когда нибудь его кто-то захочет закенселить. Исходя из этого он постоянно (на там по ходу цикла наприер) вызывает ф-цию, которая может выбросить исключение.
На самом деле в той же виндовой реализации pthreads все делается просто (при условии отсутствия драйвера, помогающего реализовать QueueUserAPCEx) — SuspendThread, SetThreadContext на коллбэк, ResumeThread. Ну а коллбэк просто кидает исключение (уже в контексте терминируемой нити). Для юзерского кода все хорошо и здорово (перехватил исключение, и дело с концом), а вот то, что операционка всегда нормально будет себя вести при таких финтах, никто не обещает.
> Блокирующий вызова в ядро (различного рода read, write и тд) > > Решение. > Это самый сложный случай из всех. И наверно именно из-за него советовали писать драйвер и другие подобные страхи (или покупать). Конечно, преимущество драйвера неоспоримо, ведь тогда он берет на себя работу по отслеживанию текущих блокировок и их корректному завершению, но тогда мы становимся его заложниками. Для большой системы это еще приемлемо, но не маленьких это неприемлемо. > Ну голь на выдумки емка, так что можно всего лишь обойтись локальным хранилищем хендлов. Разумеется, чтобы все это дело автоматизировать, придётся писать фремворк, в котором необходимо завести базовый класс HandleBase, в котором и будет проходить вся работа по помещению хендла в таблицу возможно зависших хендлов MegaThreada. > Многие скажут, что это гемор и всё такое, но на самом деле — не такой уж и гемор. > Ведь есть всего несколько видов блокирующих хендлов — File, Socket, Pipe. Но всё равно всё сходится к файлам, к ним родимым.
Про dll'ки забыл. Допустим, в убиваемой нити осуществляется загрузка какой-нибудь юзерской dll и всех dll, которые она тянет за собой. Перед вызовом DllMain Win2000 и XP блокируют какую-то свою критическую секцию. И как раз после окончания вызова DllMain (который наверняка обложен exception fraim'ом), но до отпускания критической секции осуществляется наше прибивание нити. В каком состоянии останется та критическая секция и сможет ли процесс нормально продолжить работу — фиг его знает. И это только один, самый простой, пример.
Ну а про драйвер я говорил тоже наглядевшись на pthreads — там используется вот это: http://www.codeproject.com/threads/queueuserapcex.asp?df=100&forumid=15653&exp=0&select=597532 Решение более грамотное, но не всегда приемлемое.
Posted via RSDN NNTP Server 2.0
Одним из 33 полных кавалеров ордена "За заслуги перед Отечеством" является Геннадий Хазанов.
S>Про dll'ки забыл. Допустим, в убиваемой нити осуществляется загрузка какой-нибудь юзерской dll и всех dll, которые она тянет за собой. Перед вызовом DllMain Win2000 и XP блокируют какую-то свою критическую секцию. И как раз после окончания вызова DllMain (который наверняка обложен exception fraim'ом), но до отпускания критической секции осуществляется наше прибивание нити. В каком состоянии останется та критическая секция и сможет ли процесс нормально продолжить работу — фиг его знает. И это только один, самый простой, пример. S>Ну а про драйвер я говорил тоже наглядевшись на pthreads — там используется вот это: http://www.codeproject.com/threads/queueuserapcex.asp?df=100&forumid=15653&exp=0&select=597532 Решение более грамотное, но не всегда приемлемое.
Можно привести в пример еще многое (та же подсистема user32 сос своими очередями сообщение и SendMessage-ами и тд и тп).
Но я постарался выделить наиболее основные моменты, когда используются доп. потоки.
Ведь это по большей части паралельный ввод/вывод или паралельная обработка информации. По крайней мере у меня в 98% процентах случаев нужно именно это.
И лечил я все эти случаи описанными способами. Но до написания единого фреймворка руки не доходили. Потому как много времени нужно, чтобы осознать всю глубину глубин и реализовать ее...
Про критические секции принципиально не писал, потому как зависание в них еще не разу не было (дай бог здоровья Александреску, у которого я прочитал про Lock классы).
Уж слишком быстро работают участки с их участием...
Здравствуйте, Kapone, Вы писали:
K>Наверно ты не так меня понял
я понял правильно -- ты туманно объяснил просто
K>Я имел ввиду, что все равно поток ДОЛЖЕН знать, что когда нибудь его кто-то захочет закенселить. Исходя из этого он постоянно (на там по ходу цикла наприер) вызывает ф-цию, которая может выбросить исключение.
на сам деле таких функций может быть не одна -- каждая из них называется cancelation point -- т.е. точка выходом из которой может стать исключение thread_canceled... т.е. фактически мы забиваем на системную поддержку cancelation pointов (делая неканцелябельные с точки зрения системы threadы -- чтоб ни одна сволоч не смогла нас убить без нашего ведома -- уж не знаю есь ли подобное в виндюках)
K> Какой нить длииииииинный цикл, чего делающий
зачот
K> Ожидание какого нить события (ну там в очередь пришли данные или еще чего). В этом обычно учавствуют ф-ции Wait... для Винды или select тд для Уникс
почти зачот
так как мы пишем не один тупой враппер для thread'a а семейcтво классов помогающее при разработке MT прог -- нам в том или ином виде придется делать обертки (или не тaкие уж они обертки ) над синхронизационными примитивами
реимплементя их мы встраиваем в их работу проверку на is_cancel() и выкидываем исключение...
в большенстве случаев этого ДОСТАТОЧНО -- т.к. трудно себе представить multithreaded прогу не работающую с mutex'ами и condition'ами !! -- и естественно предлагая юзеру этот stuff мы уж позаботимся о том чтоб исключения таки долетали
как было отмечено в первом пункте бывают долгие цыклы без вызовов cancellation pointов -- для этого программер (если он вменяемый расставит is_canceled() в нужных местах (т.е. это все специфично для конкретной задачи и поделать с этим мы ни чего не можем...) Однако как показывает опыт для программера вписать это в условие своих циклов сапсем не напряжно -- т.е. решение вполне удобоваримое
K> Блокирующий вызова в ядро (различного рода read, write и тд)
проблемы с блокирующимися вызовами довольно легко объезжаются -- на моей практике не было ни одного такого случая
K>Для общего же случая с "тупой" ОС боротся не получится и придется либо убивать поток лопатой(то есть Terminate), либо, засучив рукава, решать каждый конкретный случай отдельно.
насколько "тупой" должна быть ОС предоставляыющая threadы и не предоставляющаяя mutex & condition ? -- IMHO таких не бывает -- а значит для любой ОС мы сможем выкрутиться!
Здравствуйте, zaufi, Вы писали:
Z>т.е. фактически мы забиваем на системную поддержку cancelation pointов (делая неканцелябельные с точки зрения системы threadы -- чтоб ни одна сволоч не смогла нас убить без нашего ведома -- уж не знаю есь ли подобное в виндюках)
Честно говоря, не понял, что имелось ввиду под этой пространной фразой.
Если не влом, то можно поподробнее, плз
Z>почти зачот Z>так как мы пишем не один тупой враппер для thread'a а семейcтво классов помогающее при разработке MT прог -- нам в том или ином виде придется делать обертки (или не тaкие уж они обертки ) над синхронизационными примитивами Z>реимплементя их мы встраиваем в их работу проверку на is_cancel() и выкидываем исключение...
Ну я вообще это и имел ввиду, только написал чуть позже...
K>>Для общего же случая с "тупой" ОС боротся не получится и придется либо убивать поток лопатой(то есть Terminate), либо, засучив рукава, решать каждый конкретный случай отдельно. Z>насколько "тупой" должна быть ОС предоставляыющая threadы и не предоставляющаяя mutex & condition ? -- IMHO таких не бывает -- а значит для любой ОС мы сможем выкрутиться!
Это даже не ИМХО. Теоретически доказано Дейкстрой, что в многопоточной среде не обойтись без объектов синхронизации.
Другое дело, чтобы добится требуемой ф-ости только с помощью средств ОС, не гемороясь, не танцуя с бубнами и не делая фактически работу разработчиков ОС, мы требуемой ф-ости добится не можем ...
Всё равно мы приходим к тому, что остановить, кроме как ЛОПАТОЙ (или злобных и неизведанных хаков), течение потока, который даже не подозревает о том, что он работает в многопоточной среде, невозможно. А жаль ...
Так что вопрос закрыт.
Точка.
НО!
Старый код то всё равно придется модифицировать!
А это чревато новыми неизведаными багами!
так что работа у нас будет и это не может не радовать !