TProcess Detached, непонимание структуры try-finally/Free()

Вопросы программирования и использования среды Lazarus.

Модератор: Модераторы

TProcess Detached, непонимание структуры try-finally/Free()

Сообщение sunjob » 30.04.2024 19:47:53

добрый день

рассматриваю / отлаживаю создание копий приложения (имеется два варианта: "копия формы" и "создание отдельного процесса" - наш случай)
с "созданием копии" - все понятно/ожидаемо (работает, без вопросов).

напонятно "поведение/работы" кода по созданию "отдельного процесса" (точнее структура try-finally / Free )

"дочерний процесс"(*) - запускается и оба процесса работают независимо друг от друга.
можно отдельно закрыть "пораждаемый/родительский процесс", можно "дочерний/копию", т.е. все как доктор прописал и описано в хелп/вики.
(*) - процесс -> исходный бинарник, т.е. запускает еще одну купию бинарного-файла/самого себя (но, думаю, это не принципиально).
Код: Выделить всё
procedure _run_exe();
var
prc : TProcess;
i   : integer;

begin
prc := TProcess.Create(nil);
try
  prc.Executable     := exe_path+'/'+exe_fname;
  prc.InheritHandles := False;
  prc.ShowWindow     := swoShow;
  prc.Options        := [poDetached];
  for i := 1 to GetEnvironmentVariableCount do
  prc.Environment.Add(GetEnvironmentString(i));
  prc.Execute;
finally
  prc.Free;
  end; // try-finally()
end;

итак, не понятно, с точки зрения кода C/C++ - работа/"ход мыслей" структуры:
Код: Выделить всё
finally prc.Free;


код с осовобождением (prc.Free) должен сработать сразу после создания/запуска процесса, тем более при закрытии "родительского" процесса. (мы-же рассматриваем этот код из "родительско-запускаемого" процесса, а если родитель закрывается, то, данный код однозначно "должен сработать" и удалить поражденный процесс, но этого не происходит :о) - а работает все как "надо".

при чем - отладчик, и в самом деле, сразу после prc.Execute стопарИтся на данной команде, но !!! не входит внутрь prc.Free (игнорируется?!) и далее выходит из процедуры.

ВОПРОС: пожалуйста, поясните / разложите по полочкам "философию паскаля" в данном случае. можно оперировать понятиями ООП в контексте с/с++ (для более внятного пояснения :о)

п.с. пример кода
https://wiki.freepascal.org/Executing_E ... rograms/ru
Запуск отдельной программы

исходные данные
Код: Выделить всё
slackware 14.2 / 15.0 / x64
fpc-3.2.2
lazarus_2.2.6 gtk2/qt4/qt5
lazarus_3.2.0 gtk2/qt4
debug-backend: fpDebug
Аватара пользователя
sunjob
постоялец
 
Сообщения: 156
Зарегистрирован: 12.01.2011 15:19:54

Re: TProcess Detached, непонимание структуры try-finally/Fre

Сообщение Sergei I. Gorelkin » 01.05.2024 16:29:03

Экземпляр класса TProcess - это самый обычный объект в памяти, и подчиняется общим правилам работы с объектами.
С процессами как таковыми он вообще никак не связан, несмотря на то, что вызовы его методов позволяют этими процессами управлять.

Поведение отладчика на блоках try..finally - отдельный вопрос, связанный с правильностью отладочной информации. Сколько себя помню, в этой части всегда были какие-то глюки.
Аватара пользователя
Sergei I. Gorelkin
энтузиаст
 
Сообщения: 1405
Зарегистрирован: 24.07.2005 14:40:41
Откуда: Зеленоград

Re: TProcess Detached, непонимание структуры try-finally/Fre

Сообщение Alex2013 » 01.05.2024 17:46:58

Брр... (Запутался в объяснениях). Что результате то должно получится ? (Приложение может запустить еще один экземпляр "самого себя" но это точно плохая практика (Годится разве что для перезапуска ) )
(ИМХО) Надежнее сделать оболочку которая запускает отдельный "процесс-плагин"(в виде отдельного приложения в этом случае действительно можно запустить несколько экземпляров ) и контролирует все запущенные плагины . ( Имеет смысл если один плагин используется в разных приложениях (или для четкого разделения функций при возможном расширении проекта (что осбенно полезно при колетивной разработке ) ) или если плагин может быть полезен как отдельная утилита ) Кстати я тут научился встраивать плагин в окно ( или панель ) основной программы ( Просто передаю в параметрах хембл панели, а в плагине делаю SetParent - там есть небольшая проблема "с мерцанием при переключении родителя" но все решаемо )
Зы
На гифке видно как в начале "редактор настроек" запущен в режиме отдельного приложения LSetup.exe, а потом как плагин внутри оболочки (особой разницы не заметно ).
Изображение
(Разумеется пока что и "оболочка" и плагин пока не являются частью завершенного проект, а представляют из себя очередную тестовую сборку, но как иллюстрация идеи "интеграции плагина" они вполне годятся и в таком виде )
Зы Зы
Кроме того слово "процесс" у меня обычно ассоциируется не с полноформатным приложением а с классом Thread так что возможно в этом направлении и нужно копать ?
Последний раз редактировалось Alex2013 01.05.2024 23:46:25, всего редактировалось 1 раз.
Alex2013
долгожитель
 
Сообщения: 3049
Зарегистрирован: 03.04.2013 11:59:44

Re: TProcess Detached, непонимание структуры try-finally/Fre

Сообщение sunjob » 01.05.2024 19:46:15

попробую еще раз пояснить, что мне не понятно (совсем локоничный пример)
Код: Выделить всё
try
  prc.Execute;
finally
  prc.Free;
end; // try-finally()

1. наш код заключен в try-finally
2. prc.Execute - запускает процесс (который отпачковывается от нашего текущего) и, естественно, команда на этом прекращает работу
3. далее, по ходу идет блок fynally, в кот. и ... убивается процесс (только что запущенный и отпачковавашийся), точнее должен убиваться (если процесс - модально запущен, но в нашем случае - не модальный, а самостоятельный)

спрашивается какого хрена?! ведь этот код тут бессмысленен.

структура кода - один в один, try-finally по ссылке (наполнение только свое)

вот мне не понятен данный пример, зачем тут используется try-finally, если он вообще не работает (процесс запустился и стал самостоятельным)
пример структуры кода взять отседовась:
https://wiki.freepascal.org/Executing_External_Programs/ru

p.s.
Что результате то должно получится ?

получилось то, что и ожидалось (что и было "озадачено" в примере по ссылке) - запускается отдельный процесс (независимый от запускающего)
но, только непонятна структура / а нахрена try-finally()? если в данном слуае "оно" не только не работает но и бессмыслено

но это точно плохая практика (Годится разве что для перезапуска )

это очень правильная и нужная практика... в редких случаях, но единственно верная (но в данном случае не имеет принц. значения, точно так-же можно запустить любое другое приложение)

Thread ... так что возможно в этом направлении и нужно копать ?

мне нужен был не "поток" а именно отдельно запущенное приложение (читай как "еще один запущенный бинарник", только со своим окружением, арг.ком.строки)

спасибо

p.s.2 еще раз дополнительно:
данный код работает так как надо - запускает отдельный процесс и все ок, оба процесса независимы др.от друга, закрываются независимо (др.от.друга), закрытие "материнского" процесса - не убивает запущенный "дочерний" процесс...

т.е. все вроде ок! но мне не понятно
- почему в помоще/вики приводится код в обертке try-finally() - которая не работает (т.е. мы запустили процесс, отпустили его а ...гм, что удалять/убиваться то должно?! а ничего) ... и ничего не удалятеся/не убивается, хотя отладчик сразу после запуска процесса переходит на комадну удаления (но далее не идет и сразу выходит из обработчика) про то, что отладчик в лазаре как-бы не совсем хорош, это знают, наверное, не только те, кто пишет на лазаре...(ну да ладно)

по идее, все прекрасно и логично запускается без try-fynally()

а вот!!! блок try-catch() - вот его-то как раз и можно было-бы использовать в данном месте, т.е. если произошла ошибка/исключение во время запуска процесса, то вот тут-то его и надо убить... но с другой стороны опять-таки ... а кого-убивать то?! если процесс как-бы должен был отвалиться ...

вообщем пока непонимание остается :о)
Аватара пользователя
sunjob
постоялец
 
Сообщения: 156
Зарегистрирован: 12.01.2011 15:19:54

Re: TProcess Detached, непонимание структуры try-finally/Fre

Сообщение Alex2013 » 01.05.2024 21:12:08

Пишу набор банальностей для постепенного приближения к пониманию что вас так удивило .
1 Секция fynally выполняется всегда но в случае сбоя( возникновения исключения) она выполняется немедленно .
2 Разумеется ошибки в запускаемом процесс-приложении никак не отразятся на try fynally (Раве что этого можно добиться принудительной установкой "кода выхода" )
3 Ошибка может возникнуть только в prc.Environment.Add(GetEnvironmentString(i));( кстати не совсем понятно зачем это нужно "окружение" и так копируется но ладно "криминала" тут нет ) и prc.Execute;
(возможно там есть какие то тонкости при настройке свойства но это несущественно )
4 Что может вызвать ошибку в prc.Execute ? Не найден файл , файл есть но поврежден , есть какая либо системная блокировка запуска, упоминаемый выше "кода выхода" не соответствует нормальному завершению.
5 Приложение может быть запущено с ожиданием его завершения или еще каким нибудь специальными параметрами .
(что делает poDetached если честно не понял )
6 prc.Free; в общем виде не убивает процесс-приложение (для этого есть TProcess.Terminate) free это в данном случае просто освобождение памяти выделенной при создании класса .
( и если есть планы использования TProcess.Terminate в другой части программы то делать prc.Free; в секции fynally НЕ НУЖНО )
7 Возможно тут блеее осмыслен код try except ( секция except исполняется только при наличии исключения )
Код: Выделить всё
try
...
except
  prc.Free;
  prc:=nil;
end;


Вообщем "примеры из учебника" традиционно лишены конкретики и верны только при соблюдении некой абстрактной ситуации.
(В данном случае речь идет о ситуаци "заустили и забыли" ) но если програима должна будет контролировать запущенное приложение то пример с try fynally неподходит.
Последний раз редактировалось Alex2013 13.05.2024 00:20:17, всего редактировалось 2 раз(а).
Alex2013
долгожитель
 
Сообщения: 3049
Зарегистрирован: 03.04.2013 11:59:44

Re: TProcess Detached, непонимание структуры try-finally/Fre

Сообщение sunjob » 01.05.2024 21:36:17

Alex2013 писал(а):Пишу набор банальностей для приближения к пониманию что вас так удивило

это все понятно (вроде как изначально было)

не понятно вот что:
код
Код: Выделить всё
try-finally()

как так он себя ведет при
1. запуске дочернего кода и
2. удалении материнского процесса (дочерний код уже запущен и работает отдельно)

т.е. все "аварийные и заключительные" секции материнского кода - как так отрабатывают? и если отрабатывают, то "как-бы должны зачистить/удалить" этот самый запущенный процесс... (ну или, как вы говорите, непонятное мне, освобождение памяти)... к стати, надо будет заменить free-> TProcess.Terminate и посмотреть какова будет реакция на закрытие "материнского" процесса :о)

5 Приложение может быть запущено с ожиданием его завершения или еще каким нибудь специальными параметрами .

может быть и "может с ожиданием", но в данном случае:
poDetached
- запускаемый процесс сразу отключается от инициируемого !!! СРАЗУ!!! и продолжает работать независимо и в данном случае понятие "кода выхода" - бессмыслено, потому как никакого "выхода" еще нет (приложение запущено и работает)... а потом, когда "материнский" процесс удален/закрыт, при работающем "дочернем" - тем более бессмысленое понятие "код выхода"... может, после закрытия "дочернего процесса" - код и вернется, только обрабатывать его будет точно не "материнский процесс"

это просто освобождение памяти выделенной при создании класса

освобождение памяти должно производиться после удаления "обьекта", т.е. создали обьект, он захватил кусок памяти, ок?! далее, поработал обьект, закончил свою работу, его удаляют/убивают и только потом освобождают занятую им память... (что не так я понимаю?!)

делать prc.Free; в секции fynally НЕ НУЖНО

т.е. вы тоже так считаете?! по ссылке - как бы "не совсем правильный код"? так?!

спасибо
Аватара пользователя
sunjob
постоялец
 
Сообщения: 156
Зарегистрирован: 12.01.2011 15:19:54

Re: TProcess Detached, непонимание структуры try-finally/Fre

Сообщение Alex2013 » 01.05.2024 21:51:27

sunjob писал(а):poDetached
- запускаемый процесс сразу отключается !!! СРАЗУ!!! и продолжает работать независимо и в данном случае понятие "кода выхода" - бессмыслено, потому как никакого "выхода" еще нет (приложение запущено и работает)... а потом, когда "материнский" процесс удален/закрыт, при работающем "дочернем" - тем более бессмысленое понятие "кода выход"... может, после закрытия "дочернего процесса" - код и вернется, только обрабатывать его будет точно не "матиринский процесс"

Это разумеется "усугубляет " но скорее всего процесс "сам по себе" не завершится ( например при закрытии запустившего его приложения ) и без этого . (Дерево процессов удобно просто по причине возможности легкого ПРИНУДИТЕЛЬНОГО завершения всей ветки ) но при "штатном убийстве" или завершении "родительского" приложения ветка вполне может работать дальше "лишившись корня" если это не является специально прописанным поведением.

Добавлено спустя 5 минут 31 секунду:
Re: TProcess Detached, непонимание структуры try-finally/Free()
sunjob писал(а):т.е. вы тоже так считаете?! по ссылке - как бы "не совсем правильный код"? так?!

Сажем так "Этот код достаточно верен в рамах примера " но не более того .

Добавлено спустя 12 минут 11 секунд:
Re: TProcess Detached, непонимание структуры try-finally/Free()
sunjob писал(а):освобождение памяти должно производиться после удаления "обьекта", т.е. создали обьект, он захватил кусок памяти, ок?! далее, поработал обьект, закончил свою работу, его удаляют/убивают и только потом освобождают занятую им память... (что не так я понимаю?!)


Все верно ! Но тут это относятся только к классу TProcess а не к тому что но там попытался запустить. И вообще TProcess это минуточку КОМПОНЕНТ и рассчитан на использование в духе TOpenFileDialog и TSaveFileDialоg или TTimer и т.п. То есть в нормальной сиутации он создается и освобождается вместе с формой на которую кинули значок "Process1" . А пример это банально игнорирует для наглядности кода .
Последний раз редактировалось Alex2013 13.05.2024 00:21:36, всего редактировалось 1 раз.
Alex2013
долгожитель
 
Сообщения: 3049
Зарегистрирован: 03.04.2013 11:59:44

Re: TProcess Detached, непонимание структуры try-finally/Fre

Сообщение sunjob » 01.05.2024 22:20:30

уточнение по поводу "пораждаемого процесса" - запускается отдельный бинарный файл (т.е. тот-же самый бинарный файл) :о) поэтому я беру в ковычки понятия "родителя/ребенка"

TProcess ...То есть в нормальной сиутации он создается и освобождается вместе с формой на которую кинули значок "Process1"

у меня он динамически используется (на ск. я помню ... без добавления компоненты на форму)
Аватара пользователя
sunjob
постоялец
 
Сообщения: 156
Зарегистрирован: 12.01.2011 15:19:54

Re: TProcess Detached, непонимание структуры try-finally/Fre

Сообщение Alex2013 » 01.05.2024 23:43:13

sunjob писал(а):уточнение по поводу "пораждаемого процесса" - запускается отдельный бинарный файл (т.е. тот-же самый бинарный файл) :о) поэтому я беру в ковычки понятия "родителя/ребенка"

Вообщем "атака клонов" ! :D
sunjob писал(а):у меня он динамически используется (на ск. я помню ... без добавления компоненты на форму)

Это понятно . Но суть в том что вообщем виде TProcess действительно напоминает TTimer то есть создавать и уничтожать его в одной процедуре имеет смысл только если prc.Options := [ poWaitOnExit...];
Alex2013
долгожитель
 
Сообщения: 3049
Зарегистрирован: 03.04.2013 11:59:44


Вернуться в Lazarus

Кто сейчас на конференции

Сейчас этот форум просматривают: Google [Bot] и гости: 21

Рейтинг@Mail.ru