powered by simpleCommunicator - 2.0.38     © 2025 Programmizd 02
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Как закрыть handle переданный процессу в порядке наследования?
23 сообщений из 23, страница 1 из 1
Как закрыть handle переданный процессу в порядке наследования?
    #40105856
Здравствуйте, уважаемые форумчане, не могу понять как закрыть handle, который был передан процессу в порядке наследования. (файл открывается на запись для записи консольного вывода). Точнее handle этот я закрываю, но не помогает, видимо из-за наследования и передачи другому процессу.

Я как положено открываю файл, создаю процесс с передачей туда handle открытого файла. Делаю так допустим 2 раза. Потом я корректно завершаю один процесс (отправляю ему CTRL+BREAK программно). После чего если попробовать снова выполнить ту же функцию по открытию файла и созданию процесса, то пишет " Процесс не может получить доступ к файлу, так как этот файл занят другим процессом ".

Я проверил утилитой handles от SysInternals и получается, что осиротевший handle открытого файла после закрытия процесса каким-то образом остаётся висеть но уже привязанный ко второму открытому консольному процессу (который я не закрывал). Как только второй процесс закрываю - все handle освобождаются. Если в коде прописать fmShareDenyNone это решает проблему, но это же не выход, а костылище.

Второй процесс запускался с совершенно другим открытым на запись файлом для записи консольного вывода и c другой командой, это чтобы вы не подумали что я запускаю два процесса передавая им одинаковый хендл.

Что происходит и как это побороть? Мозговой штурм устраивал, но так и не смог ничего предположить что это может быть.

А теперь собственно код:

Код: pascal
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.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
var
SI: TStartUpInfo;
PI: TProcessInformation;
SP, ST: TSecurityAttributes;

begin

conout := TFileStream.Create('path', fmOpenWrite or fmShareDenyWrite);
conout.Seek(0, soFromEnd);

SetHandleInformation(conout.handle, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT);

ZeroMemory(@SI, SizeOf(TStartUpInfo));
ZeroMemory(@PI, SizeOf(TProcessInformation));
ZeroMemory(@SP, SizeOf(TSecurityAttributes));
ZeroMemory(@ST, SizeOf(TSecurityAttributes));

SP.nLength := SizeOf(TSecurityAttributes);
SP.lpSecurityDescriptor := nil;
SP.bInheritHandle := true;

ST.nLength := SizeOf(TSecurityAttributes);
ST.lpSecurityDescriptor := nil;
ST.bInheritHandle := true;

SI.cb := SizeOf(TStartUpInfo);
SI.hStdOutput := conout.handle;
SI.hStdError := conout.handle;
SI.dwFlags := STARTF_USESHOWWINDOW or STARTF_USESTDHANDLES or STARTF_FORCEOFFFEEDBACK;
SI.wShowWindow := SW_HIDE;

if CreateProcess(nil, PChar('Command'), @SP, @ST, true, CREATE_NEW_PROCESS_GROUP or NORMAL_PRIORITY_CLASS, nil, PChar('Folder'), SI, PI) then begin
    
    WaitForSingleObjectEx(PI.hProcess, INFINITE, false);
    
    if PI.hThread <> INVALID_HANDLE_VALUE then
        CloseHandle(PI.hThread);
    if PI.hProcess <> INVALID_HANDLE_VALUE then
        CloseHandle(PI.hProcess);
end;

FreeAndNil(conout);



Завершаю процесс стандартно:

Код: pascal
1.
2.
3.
4.
	
AttachConsole('pid');
GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT, 'pid');
FreeConsole;



Почему не освобождаются хэндлы - для меня загадка. Прошу помощи у гуру, заранее спасибо.
...
Рейтинг: 0 / 0
Как закрыть handle переданный процессу в порядке наследования?
    #40105873
GunSmoker
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
У тебя usage count у handle = 3. Один - у тебя, второй - у первого запущенного процесса, третий - у второго запущенного процесса. Соответственно, файл будет закрыт когда все три его отпустят. Сделают они это через CloseHandle или выйдут из процесса - не суть важно.

bInheritHandle = False поставь второму запускаемому процессу, тогда usage count будет равен 2: один у тебя и один у первого запускаемого процесса (с bInheritHandle = True).
...
Рейтинг: 0 / 0
Как закрыть handle переданный процессу в порядке наследования?
    #40105876
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Павел ВоробьевЯ как положено открываю файл, создаю процесс с передачей туда handle открытого
файла. Делаю так допустим 2 раза.

То есть ты собственными руками передаёшь этот файл двум наследникам. Чему же
удивляешься?.. Наследникам передаются все открытые хэндлы, а не только те
о которых ты думаешь. И нет, в твоём коде хэндл не закрывается сразу после
запуска дочернего процесса.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Как закрыть handle переданный процессу в порядке наследования?
    #40105877
GunSmoker
У тебя usage count у handle = 3. Один - у тебя, второй - у первого запущенного процесса, третий - у второго запущенного процесса. Соответственно, файл будет закрыт когда все три его отпустят. Сделают они это через CloseHandle или выйдут из процесса - не суть важно.

bInheritHandle = False поставь второму запускаемому процессу, тогда usage count будет равен 2: один у тебя и один у первого запускаемого процесса (с bInheritHandle = True).


Я же написал, что второй процесс запускается с другими параметрами и совершенно другим файлом и к первому отношения не имеет.
...
Рейтинг: 0 / 0
Как закрыть handle переданный процессу в порядке наследования?
    #40105878
Dimitry Sibiryakov

Павел ВоробьевЯ как положено открываю файл, создаю процесс с передачей туда handle открытого
файла. Делаю так допустим 2 раза.

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


Читайте пожалуйста внимательнее, ничего и никуда я не передаю. Каждому процессу открывается отдельный файл с отдельным хендлом, я говорю что лишь 2 раза функцию вызываю.

Если проще - то первый процесс cmd.exe пишет вывод в file.log, второй процесс cmd.exe пишет в log2.log
...
Рейтинг: 0 / 0
Как закрыть handle переданный процессу в порядке наследования?
    #40105879
GunSmoker
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Если второму процессу сделать bInheritHandle = False нельзя, то есть и другие варианты .

Вариант 1. Просто закрыть хэндл ДО запуска второго процесса. Тогда он не будет в него наследоваться, потому что не будет существовать.

Вариант 2. Запустить первый процесс и сделать у себя DuplicateHandle, указав bInheritHandle = False. Закрыть первый (наследуемый) хэндл и запустить второй процесс. Хэндл не будет наследоваться, потому что будет ненаследуемым.

Вариант 3. Использовать StartupInfoEx : STARTUPINFOEXBy default, passing TRUE as the value of the bInheritHandles parameter causes all inheritable handles to be inherited by the new process. This can be problematic for applications which create processes from multiple threads simultaneously yet desire each process to inherit different handles. Applications can use the UpdateProcThreadAttributeList function with the PROC_THREAD_ATTRIBUTE_HANDLE_LIST parameter to provide a list of handles to be inherited by a particular process.
...
Рейтинг: 0 / 0
Как закрыть handle переданный процессу в порядке наследования?
    #40105881
GunSmoker
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Павел Воробьев
Я же написал, что второй процесс запускается с другими параметрами и совершенно другим файлом и к первому отношения не имеет.


У тебя хэндл первого файла открыт в момент запуска второго процесса? Ты говоришь, что да:
Павел Воробьев
осиротевший handle открытого файла после закрытия процесса каким-то образом остаётся висеть но уже привязанный ко второму открытому консольному процессу (который я не закрывал).


Поэтому нам непонятно, что тебе непонятно.
...
Рейтинг: 0 / 0
Как закрыть handle переданный процессу в порядке наследования?
    #40105882
GunSmoker
Павел Воробьев
Я же написал, что второй процесс запускается с другими параметрами и совершенно другим файлом и к первому отношения не имеет.


У тебя хэндл первого файла открыт в момент запуска второго процесса? Ты говоришь, что да:
Павел Воробьев
осиротевший handle открытого файла после закрытия процесса каким-то образом остаётся висеть но уже привязанный ко второму открытому консольному процессу (который я не закрывал).


Поэтому нам непонятно, что тебе непонятно.


Процессы совершенно разные и запускаются с разными файлами, функции выполняются в отдельных потоках и друг о друге они вообще ничего не знают. Первый процесс cmd.exe пишет вывод в file.log, второй процесс cmd.exe пишет в log2.log

Корректно закрываю первый процесс, файл не освобождается и какого-то лешего прилипает ко второму процессу. Если запустить 10 разных процессов с разными файлами, то они будут прилипать к оставшемуся и все файлы освободятся как только закрою последний процесс.

Почему так и что делать, как сделать чтобы файл после закрытия процесса освобождался? Вот что мне не понятно)))
...
Рейтинг: 0 / 0
Как закрыть handle переданный процессу в порядке наследования?
    #40105885
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Павел ВоробьевЧитайте пожалуйста внимательнее, ничего и никуда я не передаю.

Короче, убирай из функции SetHandleInformation и bInherited. И будет тебе счастье.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Как закрыть handle переданный процессу в порядке наследования?
    #40105888
Dimitry Sibiryakov

Павел ВоробьевЧитайте пожалуйста внимательнее, ничего и никуда я не передаю.

Короче, убирай из функции SetHandleInformation и bInherited. И будет тебе счастье.


С чего бы мне это делать. Это нужно, чтобы запускаемый процесс мог писать в открытый для него файл. Консольный вывод записывается в файл. Если убрать, поток ничего никуда писать не будет, херню советуете.
...
Рейтинг: 0 / 0
Как закрыть handle переданный процессу в порядке наследования?
    #40105890
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Павел ВоробьевПочему так и что делать, как сделать чтобы файл после
закрытия процесса освобождался?

ProcessMonitor в руки и смотри в какой момент у тебя закрывается файл. Очевидно,
что ты его закрываешь слишком поздно.

Павел ВоробьевС чего бы мне это делать.

С документации:
https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/ns-processthreadsapi-startupinfoa
Но таки да, bInheritHandles убирать не нужно.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Как закрыть handle переданный процессу в порядке наследования?
    #40105895
Dimitry Sibiryakov

Павел ВоробьевПочему так и что делать, как сделать чтобы файл после
закрытия процесса освобождался?

ProcessMonitor в руки и смотри в какой момент у тебя закрывается файл. Очевидно,
что ты его закрываешь слишком поздно.

Павел ВоробьевС чего бы мне это делать.

С документации:
https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/ns-processthreadsapi-startupinfoa
Но таки да, bInheritHandles убирать не нужно.


Спасибо огромное, поставил FreeAndNil(conout); сразу после CreateProcess и всё нормализовалось! Респект )))
...
Рейтинг: 0 / 0
Как закрыть handle переданный процессу в порядке наследования?
    #40105896
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Павел Воробьевфункции выполняются в отдельных потоках и друг о друге они вообще ничего не знают.

Неверно. Запускаемый процесс наследует ВСЕ хэндлы запускающего. Вне
зависимости от того в каком потоке они были открыты.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Как закрыть handle переданный процессу в порядке наследования?
    #40105898
Dimitry Sibiryakov

Павел Воробьевфункции выполняются в отдельных потоках и друг о друге они вообще ничего не знают.

Неверно. Запускаемый процесс наследует ВСЕ хэндлы запускающего. Вне
зависимости от того в каком потоке они были открыты.


Спасибо, учту. Видимо по этому хендлы и прилипали к оставшимся процессам. Я почему-то думал что OmniThreadLibrary всё изолирует внутри потока.
...
Рейтинг: 0 / 0
Как закрыть handle переданный процессу в порядке наследования?
    #40105903
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Павел Воробьевпоставил FreeAndNil(conout); сразу после CreateProcess и всё нормализовалось!

Просто окно гонок потоков стало и тебе повезло на этот раз. Лучше таки запуск
дочерних процессов жёстко сериализовать.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Как закрыть handle переданный процессу в порядке наследования?
    #40105912
Dimitry Sibiryakov

Павел Воробьевпоставил FreeAndNil(conout); сразу после CreateProcess и всё нормализовалось!

Просто окно гонок потоков стало и тебе повезло на этот раз. Лучше таки запуск
дочерних процессов жёстко сериализовать.


Еще раз перечитал ваши ответы, и только сейчас пришло осознание. Получается да, просто повезло и проблему это не решает. Получает когда я запускаю допустим 100 разных процессов пишущие в 100 разных файлов (консольный вывод) и делаю это параллельно через потоки, то им передаются ВСЕ открытые хендлы, и файлов, и потоков и всего всего всего. Это получается как снежный ком, более поздним процессам будет передаваться огромная куча отрытых хенлов для других процессов?

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

GunSmoker подал идеи, но там я так понял всё для последовательного запуска. GunSmoker может есть идеи как сделать всё параллельно? Я в печали( использовать StartupInfoEx.

GunSmoker, подскажите пожалуйста, у вас нет в загашнике примера кода для StartupInfoEx чтобы один хендл передать?
...
Рейтинг: 0 / 0
Как закрыть handle переданный процессу в порядке наследования?
    #40105921
Всё, ответ нашел тут: https://stackoverflow.com/questions/60563608/how-to-pass-a-pointer-to-a-list-of-handles-to-the-updateprocthreadattribute-func

Всем большое спасибо, GunSmoker, благодарю за наводку :)
...
Рейтинг: 0 / 0
Как закрыть handle переданный процессу в порядке наследования?
    #40105922
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Павел ВоробьевНо смотрите, если я сериализую запуск, я понимаю что это решит проблему на
корню, но это замедлит старт в 10 раз.
Нет, не замедлит если сделать всё правильно.

Замедлить в 10 и более раз как раз способен одновременный запуск при котором
бутылочным горлышком становится диск с позиционированием.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Как закрыть handle переданный процессу в порядке наследования?
    #40105927
Dimitry Sibiryakov

Павел ВоробьевНо смотрите, если я сериализую запуск, я понимаю что это решит проблему на
корню, но это замедлит старт в 10 раз.

Нет, не замедлит если сделать всё правильно.

Замедлить в 10 и более раз как раз способен одновременный запуск при котором
бутылочным горлышком становится диск с позиционированием.


Возможно, но зачем делать последовательно, если как оказалось есть возможность сделать параллельно через StartupInfoEx и передачу процессу только одного хэндла.
...
Рейтинг: 0 / 0
Как закрыть handle переданный процессу в порядке наследования?
    #40105935
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Павел Воробьевно зачем делать последовательно, если как оказалось есть возможность сделать
параллельно

Повторяю медленно: затем, что параллельный запуск может быть в 10 и более раз
медленнее.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Как закрыть handle переданный процессу в порядке наследования?
    #40105969
Fr0sT-Brutal
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
А зачем так извращаться, если можно дочерним процессом писать в STDOUT?
...
Рейтинг: 0 / 0
Как закрыть handle переданный процессу в порядке наследования?
    #40105980
Fr0sT-Brutal
А зачем так извращаться, если можно дочерним процессом писать в STDOUT?


Можно конечно, но запускаются совершенно разные процессы делающие совершенно разную работу, нельзя смешивать вывод, а вот записать его нужно обязательно. Некоторые инженерные программы сами в файл не умеют, только в консоль.
...
Рейтинг: 0 / 0
Как закрыть handle переданный процессу в порядке наследования?
    #40106099
Fr0sT-Brutal
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Павел Воробьев
Можно конечно, но запускаются совершенно разные процессы делающие совершенно разную работу, нельзя смешивать вывод, а вот записать его нужно обязательно. Некоторые инженерные программы сами в файл не умеют, только в консоль.

И как это противоречит тому, что я предложил? Пусть себе пишут в консоль, а ты лови вывод и пиши уже куда душе угодно
...
Рейтинг: 0 / 0
23 сообщений из 23, страница 1 из 1
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Как закрыть handle переданный процессу в порядке наследования?
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]