Здравствуйте, UberPsychoSvin, Вы писали:
UPS>Зависло после Log.Warn("aborting thread : " + thread.Name); ему просто негде больше зависнуть, кроме как на thread.Abort();. Вот какого хрена?
А инструкцию читать не пробовали?
The thread that calls Abort might block if the thread that is being aborted is in a protected region of code, such as a catch block, finally block, or constrained execution region. If the thread that calls Abort holds a lock that the aborted thread requires, a deadlock can occur.
Кучу раз ведь обсуждалось: единственный способ не огрести проблем с thread.Abort() — не использовать его вообще.
P.S. "ему просто негде больше зависнуть" проверяется подключением отладчика и проверкой стека "зависших" потоков. Неоднократно наблюдал (да и сам участвовал) цепочку "да нечему там падать!" -> "как мы раньше не заметили???".
Здравствуйте, Sinix, Вы писали:
S>Здравствуйте, UberPsychoSvin, Вы писали:
UPS>>Зависло после Log.Warn("aborting thread : " + thread.Name); ему просто негде больше зависнуть, кроме как на thread.Abort();. Вот какого хрена?
S>А инструкцию читать не пробовали? S>
S>The thread that calls Abort might block if the thread that is being aborted is in a protected region of code, such as a catch block, finally block, or constrained execution region. If the thread that calls Abort holds a lock that the aborted thread requires, a deadlock can occur.
S>(c)
S>Кучу раз ведь обсуждалось: единственный способ не огрести проблем с thread.Abort() — не использовать его вообще.
S>P.S. "ему просто негде больше зависнуть" проверяется подключением отладчика и проверкой стека "зависших" потоков. Неоднократно наблюдал (да и сам участвовал) цепочку "да нечему там падать!" -> "как мы раньше не заметили???".
Эммм, ну вообще да, у меня там у каждого треда в finally{} локи которые отпускаются только после всех Thread.Abort().
Но экспериментик показал что всё норм и я успокоился, а оно оказывается и так и сяк может.
Здравствуйте, UberPsychoSvin, Вы писали:
UPS>Такой вопрос, а чем килять треды, если не Thread.Abort().
Ничем. В общем случае (т.е. если вы специально не затачивали весь код под прерывание потоков) после Thread.Abort состояние программы можно рассматривать как повреждённое: где-то "завис" флаг или блокировка, где-то — не отписались от события, там валяется открытый файл или соединение, тут — недоинициализированный объект...
Используйте таски вместе с CancellationToken и не мучайтесь.
Здравствуйте, Sinix, Вы писали:
S>Здравствуйте, UberPsychoSvin, Вы писали:
UPS>>Такой вопрос, а чем килять треды, если не Thread.Abort(). S>Ничем. В общем случае (т.е. если вы специально не затачивали весь код под прерывание потоков) после Thread.Abort состояние программы можно рассматривать как повреждённое: где-то "завис" флаг или блокировка, где-то — не отписались от события, там валяется открытый файл или соединение, тут — недоинициализированный объект...
S>Используйте таски вместе с CancellationToken и не мучайтесь.
Я и так использую такой подход у себя, но виснет чужое апи. А оно сделано так что там совсем ничего не кэнселится.
Здравствуйте, UberPsychoSvin, Вы писали:
S>>Используйте таски вместе с CancellationToken и не мучайтесь. UPS>Я и так использую такой подход у себя, но виснет чужое апи. А оно сделано так что там совсем ничего не кэнселится.
Надавать по ушам автору или заменить код. Других вариантов, увы, не предусмотрено
Если других вариантов нет:
* можно запускать "подозрительный" код в отдельном домене и в случае чего убивать домен целиком.
* можно просмотреть глючный код через ilspy/dotpeek и убедиться, что код не имеет разделяемого состояния. Если повезло, то в принципе можно убивать поток. Если не повезло — см предыдущий пункт. Проверку кода придётся повторять после каждого обновления библиотеки.
Здравствуйте, Sinix, Вы писали:
S>Здравствуйте, UberPsychoSvin, Вы писали:
S>>>Используйте таски вместе с CancellationToken и не мучайтесь. UPS>>Я и так использую такой подход у себя, но виснет чужое апи. А оно сделано так что там совсем ничего не кэнселится.
S>Надавать по ушам автору или заменить код. Других вариантов, увы, не предусмотрено
Я ни разу такого апи не видел что бы всё жадное по времени кэнселилось. Может в будущем это и станет реальностью.
S>Если других вариантов нет: S>* можно запускать "подозрительный" код в отдельном домене и в случае чего убивать домен целиком.
Я вызываю ThreadAbortException что бы у меня при стопе сервиса отработали все финализаторы. Убивать целиком смысла не вижу. Уж проще выкинуть все ThreadAbort и позволить винде убить процесс.
Наверно я перестрою логику так, что бы у меня ничего не дедлочилось, и буду по прежнему абортить зависшие треды.
Здравствуйте, Sinix, Вы писали:
S>Здравствуйте, UberPsychoSvin, Вы писали:
UPS>>Я вызываю ThreadAbortException что бы у меня при стопе сервиса отработали все финализаторы.
S>Для этого Thread.Abort() нафиг не нужен. Наоборот, он может способствовать утечке ресурсов (хотя для этого надо постараться): S>
try finally никто не отменял. И я их пишу, так как exceptions тоже никуда не делись.
UPS>>Наверно я перестрою логику так, что бы у меня ничего не дедлочилось, и буду по прежнему абортить зависшие треды. S>Ну... удачи
Согласен, от проблем он не избавиться. Отдельные процессы было бы понадежней.
Здравствуйте, Sinix, Вы писали:
S>Здравствуйте, UberPsychoSvin, Вы писали:
UPS>>Я вызываю ThreadAbortException что бы у меня при стопе сервиса отработали все финализаторы.
S>Для этого Thread.Abort() нафиг не нужен. Наоборот, он может способствовать утечке ресурсов (хотя для этого надо постараться): S>
UPS>>Наверно я перестрою логику так, что бы у меня ничего не дедлочилось, и буду по прежнему абортить зависшие треды. S>Ну... удачи
Вот конкретика. У нас виндовый сервис. Нам нужно обработать его остановку.
1. Я устанавливаю кэнселейшен флаги
2. Жду таймаут.
3. Если есть висящие треды, вызываю им аборт.
try
{
//чего то там делаем
//потенциально_зависшее_место
//чего то там делаем
//чего то там делаем
//чего то там делаем
}
finally
{
//делаем чего то критичное, что надо по любому сделать.
}
из всех потенциально_зависшее_место, кидается эксцепшен, все треды им проносит, и отрабатывают все нужные финализаторы.
Вынести каждое потенциально_зависшее_место в отдельный сервис или в обёртку в AppDomain конечно можно, но это стрельба из пушки по воробьям. )
Есть какие-нибудь ещё подходы, что бы без Thread.Abort() ?
Здравствуйте, UberPsychoSvin, Вы писали:
UPS>Есть какие-нибудь ещё подходы, что бы без Thread.Abort() ?
Ну блин С "У нас виндовый сервис. Нам нужно обработать его остановку." и надо было начинать. Сценарий редкий: вам не важно состояние потоков после Abort(), система всё равно всё прибьёт.
Thread.Abort + убедиться, что остальной код не завязан на блокировки с зависающими потоками (вы и сами уже нашли этот момент) — что тут ещё думать-то?
S>>* можно запускать "подозрительный" код в отдельном домене и в случае чего убивать домен целиком. A>Не поможет, там та же самая проблема, что и с Thread.Abort.
В смысле?
Все ресурсы освободятся (если к ним есть финалайзеры, конечно). Разделяемого состояния между доменами обычно или нет вообще, или оно управляется хост-доменом. Native-код пока не рассматриваем. Что ещё может поломать состояние так, чтобы от этого не спасла выгрузка домена?