Форум программистов, компьютерный форум CyberForum.ru
Наши страницы

Delphi и WinAPI

Войти
Регистрация
Восстановить пароль
 
ymv
0 / 0 / 0
Регистрация: 15.06.2016
Сообщений: 6
#1

Кильнуть собственный тред - Delphi WinAPI

15.06.2016, 09:20. Просмотров 674. Ответов 14
Метки нет (Все метки)

Господа!

Требуется кильнуть тред (TThread), запущенный в своем процессе.
Есть такой код, которым в свое время пользовался успешно для киляния процессов. Так вот, с собственным тредом он не работает.
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
Var
 hToken:THandle;
 hProcess:THandle;
 tkp:TTokenPrivileges;
 buffer:DWord;
 iErr:integer;
 
// вот тут возникает ошибка "Неверный дескриптор" в обоих случаях:
if not Windows.OpenProcessToken(Thread.ThreadID,TOKEN_ADJUST_PRIVILEGES,hToken) ...
// if not Windows.OpenProcessToken(Thread.handle,TOKEN_ADJUST_PRIVILEGES,hToken)
 
// Ну а дальше идти смысла нет...
 
if not Windows.LookupPrivilegeValue(nil,'SeDebugPrivilege',tkp.Privileges[0].Luid)...
tkp.PrivilegeCount:=1;
 tkp.Privileges[0].Attributes:=SE_PRIVILEGE_ENABLED;
 if not Windows.AdjustTokenPrivileges(hToken,FALSE,tkp,0,nil,buffer)...
Windows.CloseHandle(hToken);
CloseHandle(Thread.ThreadID);
 hProcess:=OpenProcess(PROCESS_TERMINATE,true,Thread.ThreadID);
 if hProcess<>0 then
                begin
                TerminateProcess(hProcess,0);
                CloseHandle(hProcess);
                end
0
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
15.06.2016, 09:20
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Кильнуть собственный тред (Delphi WinAPI):

Создать собственный класс - Delphi
Создать собственный класс. Зарегистрировать его в делфи как компоненту на собственной закладке. Создать приложение, иллюстрирующее...

Как написать собственный компилятор - Delphi
Пишу среду программирования. Нужен компилятор (код для создания exe-файла).

Как создать собственный формат файлов - Delphi
Как обеспечить создание собственных форматов файлов, допустим создать на листе формы канве или отчете, и создать документ своего формата...

Собственный навигатор в БД - Delphi БД
Нужно сделать кнопки, примерно как стандартный навигатор. Чтобы можно было удалять, добавлять, редактировать и также сделать фильтр поиск...

Собственный Proxy - Сети
Доброго времени суток. Есть такая проблема: на работе интернет настроен через местный прокси, на нем фаервол режет все что только...

Собственный интерфейс - C++ WinAPI
У меня такой вопрос, допустим я делаю прогу и хочу выделить её оригинальным видом кнопок, полос прокрутки, списков и т.д. Как это...

Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
AllFree
Заблокирован
19.07.2016, 18:43 #2
Ну естественно, потому, что Вы, очевидно, передаёте MainThreadId, вместо PID.

Код
procedure TForm1.Button1Click(Sender: TObject);
const
  PROCESS_TERMINATE = $0001;
begin
  TerminateProcess(OpenProcess(PROCESS_TERMINATE,BOOL(0),GetCurrentProcessId),0);
end;
0
ymv
0 / 0 / 0
Регистрация: 15.06.2016
Сообщений: 6
19.07.2016, 20:34  [ТС] #3
А всё оказалось просто:

TerminateThread(Thread.Handle,0);
0
MINO
12 / 12 / 4
Регистрация: 03.06.2016
Сообщений: 78
02.09.2016, 21:49 #4
Зачем же так жестко с процессом то, а если в этот момент процессу что то мешать будет. Не лучше послать процессу ивент на закрытие.
0
ymv
0 / 0 / 0
Регистрация: 15.06.2016
Сообщений: 6
03.09.2016, 15:49  [ТС] #5
Это все понятно, эвент посылаеццо, но если он после некоторого таймаута не застопарился, значит всё.
0
MINO
12 / 12 / 4
Регистрация: 03.06.2016
Сообщений: 78
03.09.2016, 20:10 #6
Если ивент послан, а он не закрылся значит где то ошибка, а всякими TerminateThread вы только аксес валейшен получите.
1
ymv
0 / 0 / 0
Регистрация: 15.06.2016
Сообщений: 6
04.09.2016, 09:44  [ТС] #7
Простейший пример. Тред обращается к какому-то серверу по Интернету - для чего и писался.
Сервер завис или пинг исчез, а прогу закрывать надо, она работает по расписанию. Таймаута от сервера ждать некогда. Вот поэтому подобные обращения и пишу тредами, чтобы можно было их кильнуть и хоть прогу завершить корректно.
0
Убежденный
Системный программист
Эксперт С++
15545 / 7053 / 1114
Регистрация: 02.05.2013
Сообщений: 11,466
Завершенные тесты: 1
04.09.2016, 09:53 #8
ymv, тебе надо тогда делать terminate всему процессу, а не отдельному потоку.
0
Fulcrum_013
717 / 742 / 73
Регистрация: 14.12.2014
Сообщений: 5,830
Завершенные тесты: 3
04.09.2016, 09:59 #9
Цитата Сообщение от ymv Посмотреть сообщение
Требуется кильнуть тред (TThread), запущенный в своем процессе.
Специально для этой задачи у TThread имеется метод Terminate();
0
ymv
0 / 0 / 0
Регистрация: 15.06.2016
Сообщений: 6
04.09.2016, 11:47  [ТС] #10
>тебе надо тогда делать terminate всему процессу, а не отдельному потоку.

Нет, не надо. Весь процесс - это прога, она должна корректно завершиться. Тред обращается к серверу в Интернете, он может подвиснуть, но прога висеть не должна. Teleport Pro юзал, надеюсь? Там тот же принцип: 10 тредов качают, головной процесс ими управляет.

>Специально для этой задачи у TThread имеется метод Terminate();

Будет работать, когда тред висит? Suspend() точно не работает в этом случае, тред тут должен реагировать на эвенты. Terminate() уж не помню, пробовал, нет, наверно тоже самое.

Добавлено через 5 минут
P.S. Ну да, Terminate() в этой ситуации точно работать не будет, судя по описалову:

>Terminate sets the thread's Terminated property to true, signaling that the thread should be terminated as soon as possible.

Знаем, играли. Когда тред висит в описанной выш5е ситуации, штатные методы TThread не работают.
0
Убежденный
Системный программист
Эксперт С++
15545 / 7053 / 1114
Регистрация: 02.05.2013
Сообщений: 11,466
Завершенные тесты: 1
04.09.2016, 11:53 #11
Цитата Сообщение от ymv Посмотреть сообщение
Весь процесс - это прога, она должна корректно завершиться.
Так в том-то и дело, что если прибить один из потоков, гарантии корректного
завершения всей программы уже нету. Например, поток может быть убит при
захваченной блокировке LoaderLock в ntdll (она захватывается при загрузке/
выгрузке dll, при запуске и уничтожении потоков, при вызове RtlUnwind на x64 и
некоторых других функциях). В итоге при завершении программы штатными
методами процесс легко может повиснуть или выкинуть еще какую-нибудь штуковину.
0
Fulcrum_013
717 / 742 / 73
Регистрация: 14.12.2014
Сообщений: 5,830
Завершенные тесты: 3
04.09.2016, 13:45 #12
Цитата Сообщение от ymv Посмотреть сообщение
Знаем, играли. Когда тред висит в описанной выш5е ситуации, штатные методы TThread не работают.
Ну приделай к ней свой метод который ее через TerminateThread похоронит. Только такое ее снятие очень не полезное для системы.

Добавлено через 4 минуты
Цитата Сообщение от ymv Посмотреть сообщение
Тред обращается к какому-то серверу по Интернету - для чего и писался.
В дельфе у всех средств работы с инетом и сокетами асинхронная работа и таймауты реализованы прекрасно. Так же как и в WinAPI. Что там настолько нештатное что понадобилось с потоками висящими на синхронных вызовах лисапед лисапедить?
0
ymv
0 / 0 / 0
Регистрация: 15.06.2016
Сообщений: 6
04.09.2016, 14:44  [ТС] #13
>Что там настолько нештатное что понадобилось с потоками висящими на синхронных вызовах лисапед лисапедить?

Да не то чтобы настолько нештатное, просто на автомате всегда так делаю. Может подвиснуть или что - надо делать тредом и его килять во внештатных ситуациях. Тем более эта утиль предназначена для пакетной работы, значит должна работать как часы. И работает.

И не такая уж надёжная штука дельфя и винды, чтобы говорить, что не повиснет. Как минимум подстраховаться надо.

>при захваченной блокировке LoaderLock в ntdll (она захватывается при загрузк...

Ничего такого системного там нет. Никаких "глобальных" блокировок. Тред предельно изолирован.
0
Fulcrum_013
717 / 742 / 73
Регистрация: 14.12.2014
Сообщений: 5,830
Завершенные тесты: 3
04.09.2016, 15:01 #14
Цитата Сообщение от ymv Посмотреть сообщение
Может подвиснуть или что - надо делать тредом и его килять во внештатных ситуациях
касательно сокетов, инет дел и всего что может работать асинхронно это very very bad practicle.

Добавлено через 2 минуты
Цитата Сообщение от ymv Посмотреть сообщение
Как минимум подстраховаться надо.
В винапи подстраховано гораздо надежней и спящим тредом. На самом деле все синхронные варианты функций работают ожиданием события от асинхронного варианта.

Добавлено через 4 минуты
Дельфи в этом плане только оборачивает WinAPI

Добавлено через 1 минуту
Единственное что реально требует такого подхода с потоком для таймаута - работа с COM и LPT портами там асинхронных вариантов почему то нет.
0
Убежденный
Системный программист
Эксперт С++
15545 / 7053 / 1114
Регистрация: 02.05.2013
Сообщений: 11,466
Завершенные тесты: 1
04.09.2016, 15:35 #15
Цитата Сообщение от ymv Посмотреть сообщение
Ничего такого системного там нет. Никаких "глобальных" блокировок. Тред предельно изолирован.
Во-первых, при уничтожении треда не вызывается DLL_THREAD_DETACH в dll, а значит,
если с потоком были связаны какие-то данные (хранящиеся, например, в TLS), то
они освобождены не будут. Вот и утечка уже.

Во-вторых, полностью изолированных потоков в Win32 не может быть по определению, а
захват ntdll!LoaderLock выполняется намного чаще, чем обычно принято думать.

В-третьих, даже если поток кажется зависшим, все равно нет никакой гарантии, что он
не "развиснет" одновременно с вызовом TerminateThread. И тогда может быть, что
поток прибьют как раз в тот момент, когда он выполняет метод какого-нибудь объекта, в
результате чего объект останется в неопределенном состоянии.

Я таких багов за последние годы повидал сотню, если не больше: сначала кто-то
делает "безобидный" kill потоку в одном месте, а валится потом в совсем другом,
иногда минуты или часы позже.

Так что я все равно буду нудно талдычить, что TerminateThread - это последнее
средство, крайняя мера, и после него состояние всего процесса неопределено,
можно сразу делать TerminateProcess.

----

Ладно, если уже на то пошло и кроме TerminateThread совсем-совсем ничего нет,
тогда надо прибивать поток, только делать это по-другому, более безопасным способом.
Например, сделать для потока SetThreadContext, направив его в какую-нибудь
функцию, где он сможет сам для себя вызвать ExitThread и, соответственно, вызвать
все нужные деструкторы и нотификаторы DLL_THREAD_DETACH.
0
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
04.09.2016, 15:35
Привет! Вот еще темы с ответами:

Собственный стек - C#
Было задание написать собственный стек. Я хоть и написал но возникли вопросы в функции Push. public void Push(T item) { ...

Собственный InputBox - C#
Как сделать inputBox так, чтобы он возвращал значение как метод. Вроде string text = InputBox(&quot;Введите значение&quot;); появляется форма,...

Собственный вектор - Алгебра
Здравствуйте, подскажите как найти матрицу для собственного вектора ? (-1) 1 -1 Добавлено через 13 минут +вопросик ) если...

собственный GUI - Visual C++
Здравствуйте. Пишу программы с использованием Windows API. Все нравиться и получается 8-) Надоедает скудный дизайн Windows 98 forever...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
Yandex
Объявления
04.09.2016, 15:35
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru