[SOLVED] Process.Terminate(0); not working lazarus / 32-Linux ---------------------------------------------------------------------- petevick · 2024-05-19 11:04 The Process.Terminate(0) is not closing the app that was executed by Process in Linux, it only terminates the process, but it works fine in Windows. Is there another method for closing an app that was executed by a TProcess ?? ---------------------------------------------------------------------- Thaddy · 2024-05-19 15:08 What works fine in Windows? You asked it to terminate, so it obliges...  also on Linux. ---------------------------------------------------------------------- petevick · 2024-05-19 16:04 Quote from: Thaddy on May 19, 2024, 05:08:15 pmWhat works fine in Windows? You asked it to terminate, so it obliges...  also on Linux. That's my point, Process.Terminate(0) DOESN'T work in Linux, the app remains open.... Quote from: petevick on May 19, 2024, 01:04:46 pmThe Process.Terminate(0) is not closing the app that was executed by Process in Linux, it only terminates the process, ........ ....it could be that the app is not responding to Terminate in Linux, but it does in Windows. ---------------------------------------------------------------------- petevick · 2024-05-20 07:29 It would appear that not all applications respond to the Process.Terminate(0) method in Linux, I've tried several third party apps, FreeFileSync does not respond, neither does Qcad (the app that I'm dealing with), but Meld does respond, all the system apps such as xed do respond. ---------------------------------------------------------------------- MarkMLl · 2024-05-20 08:07 Quote from: petevick on May 20, 2024, 09:29:04 amIt would appear that not all applications respond to the Process.Terminate(0) method in Linux, I've tried several third party apps, FreeFileSync does not respond, neither does Qcad (the app that I'm dealing with), but Meld does respond, all the system apps such as xed do respond. What is it actually doing? This might be the difference between a kill and term signal... if in doubt try using another TProcess to invoke killall (or a targeted kill if you know the PID). MarkMLl ---------------------------------------------------------------------- petevick · 2024-05-20 09:06 Quote from: MarkMLl on May 20, 2024, 10:07:15 amWhat is it actually doing? This might be the difference between a kill and term signal... if in doubt try using another TProcess to invoke killall (or a targeted kill if you know the PID). MarkMLl It's doing nothing, I can execute the app using TProcess.Execute, the app fires up and displays, when I issue Process.Terminate(0) the process is terminated but the app remains open. I've tried a targeted kill, same result, the app remains open. ---------------------------------------------------------------------- MarkMLl · 2024-05-20 09:21 Quote from: petevick on May 20, 2024, 11:06:16 amIt's doing nothing, I can execute the app using TProcess.Execute, the app fires up and displays, when I issue Process.Terminate(0) the process is terminated but the app remains open. I've tried a targeted kill, same result, the app remains open. In that case either you're killing it wrong, or your system's broken. MarkMLl ---------------------------------------------------------------------- TRon · 2024-05-20 10:10 Quote from: petevick on May 19, 2024, 01:04:46 pmThe Process.Terminate(0) is not closing the app that was executed by Process in Linux, it only terminates the process, but it works fine in Windows. Windows works completely different than Linux in that regards so that is not a valid comparison. What app exactly does not seem to obey the Linux signal handling ? Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i Function TProcess.Terminate(AExitCode : Integer) : Boolean; begin  Result:=False;  Result:=fpkill(Handle,SIGTERM)=0;  If Result then    begin    If Running then      Result:=fpkill(Handle,SIGKILL)=0;    end;  { the fact that the signal has been sent does not    mean that the process has already handled the    signal -> wait instead of calling getexitstatus }  if Result then    WaitOnExit;end;  edit: I just noticed this thread being marked as solved. so this reply seem to be redundant. Still would like to know what the issue was though ---------------------------------------------------------------------- petevick · 2024-05-20 10:23 Quote from: TRon on May 20, 2024, 12:10:15 pmQuote from: petevick on May 19, 2024, 01:04:46 pmThe Process.Terminate(0) is not closing the app that was executed by Process in Linux, it only terminates the process, but it works fine in Windows. Windows works completely different than Linux in that regards so that is not a valid comparison. What app exactly does not seem to obey the Linux signal handling ? Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i Function TProcess.Terminate(AExitCode : Integer) : Boolean; begin  Result:=False;  Result:=fpkill(Handle,SIGTERM)=0;  If Result then    begin    If Running then      Result:=fpkill(Handle,SIGKILL)=0;    end;  { the fact that the signal has been sent does not    mean that the process has already handled the    signal -> wait instead of calling getexitstatus }  if Result then    WaitOnExit;end;  edit: I just noticed this thread being marked as solved. so this reply seem to be redundant. Still would like to know what the issue was though  I've just removed '[SOLVED]' The app is called Qcad, I've also tried FreeFileSync which also refuses to die. Other apps like xed die without any argument. This is why I marked as [SOLVED] as I believe it to be a particularity of the app rather than a fault with with Lazarus. I'm using..... Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i     fpKill(Proc.ProcessID, SIGKILL);    Proc.WaitOnExit(); ....to kill the app but the app remains displayed. ---------------------------------------------------------------------- TRon · 2024-05-20 10:40 Quote from: petevick on May 20, 2024, 12:23:47 pmThe app is called Qcad, I've also tried FreeFileSync which also refuses to die. Other apps like xed die without any argument. This is why I marked as [SOLVED] as I believe it to be a particularity of the app rather than a fault with with Lazarus. In principle it is indeed not he fault of Lazarus rather that of the application not obeying the rules as agreed upon. I find it remarkable as both apps you mentio0ned seem to be pure c-applications (so there is no excuses whatsoever). QuoteI'm using..... Yeah that should work though depending on the app a sigterm might work better. How do these apps behave when you try to kill them using system tools ?, see also here ---------------------------------------------------------------------- MarkMLl · 2024-05-20 10:49 Quote from: petevick on May 20, 2024, 12:23:47 pmThe app is called Qcad, I've also tried FreeFileSync which also refuses to die. Other apps like xed die without any argument. This is why I marked as [SOLVED] as I believe it to be a particularity of the app rather than a fault with with Lazarus. What does ps tell you? What happens if you use kill from the shell? With -KILL? With -TERM? Stop fossicking around with TProcess for the moment, since what you've probably got is a wrapper (possibly a shell script) which is what your program has actually started, which in turn starts off a binary without explicitly giving you a PID etc. A killed process CANNOT keep running. The kill could fail because you didn't have adequate privilege or the process could be moved to a zombie state. And that's basically what I meant by my "you're killing it wrong" quip: you need to sort out how Qcad is running- i.e. shell- level work- before you have a hope of doing it from inside your program (even with a kill or a killall, for which you need the pid or true name respectively). MarkMLl ---------------------------------------------------------------------- petevick · 2024-05-20 10:51 Quote from: TRon on May 20, 2024, 12:40:50 pm[How do these apps behave when you try to kill them using system tools ?, see also here I've tried sigterm, same result  I've just tried capturing the ProcessID which was 26715, and then entered 'kill 26715' in the terminal, the command ran without error, but Qcad reamined displayed. I'll check out your link next. ---------------------------------------------------------------------- TRon · 2024-05-20 10:58 @petevick: The link basically tells what MarkMLI is suggesting. It slipped my mind but indeed it is quite possible the system runs the app using a 3th party launcher (solution) in which case things work differently/unexpected. Just try to obtain all the information from a terminal and use the same terminal (or suggested tools in the posted link), e.g. what MarkMLI also suggested to be able to tell if behaviour differs. ---------------------------------------------------------------------- petevick · 2024-05-20 11:07 Quote from: TRon on May 20, 2024, 12:58:22 pm@petevick: The link basically tells what MarkMLI is suggesting. It slipped my mind but indeed it is quite possible the system runs the app using a 3th party launcher (solution) in which case things work differently/unexpected. Just try to obtain all the information from a terminal and use the same terminal (or suggested tools in the posted link), e.g. what MarkMLI also suggested to be able to tell if behaviour differs. Yes, I'm beginning to understand what's happening now. Qcad does indeed run from a launcher. I've used ps -A in terminal and qcad and qcad-bin are listed, using the PID for qcad-bin, the kill command does finally kill Qcad. ---------------------------------------------------------------------- TRon · 2024-05-20 11:20 Quote from: petevick on May 20, 2024, 01:07:17 pmYes, I'm beginning to understand what's happening now. Qcad does indeed run from a launcher. I've used ps -A in terminal and qcad and qcad-bin are listed, using the PID for qcad-bin, the kill command does finally kill Qcad. There you go  . MarkMLI was a bit more focused than I was... Now the question becomes what you want to do about it and what you can do about it (depending on the purpose of your application/tprocess launcher) I have to admit that is a bit cloudy for me as well.... e.g.  I do not know if there is an universal way to be able to always kill everything some initial process launched. ---------------------------------------------------------------------- petevick · 2024-05-20 11:28 Quote from: TRon on May 20, 2024, 01:20:07 pmQuote from: petevick on May 20, 2024, 01:07:17 pmYes, I'm beginning to understand what's happening now. Qcad does indeed run from a launcher. I've used ps -A in terminal and qcad and qcad-bin are listed, using the PID for qcad- bin, the kill command does finally kill Qcad. There you go  . MarkMLI was a bit more focused than I was... Now the question becomes what you want to do about it and what you can do about it (depending on the purpose of your application/tprocess launcher) I have to admit that is a bit cloudy for me as well.... e.g.  I do not know if there is an universal way to be able to always kill everything some initial process launched. I've noticed in the ps -A output that the PID for qcad-bin has always been the PID for qcad plus 1, the qcad PID is what Process.ProcessID gives. I'm thinking that this is not reliable though, but if I change my code above to...... Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i     fpKill(Proc.ProcessID + 1, SIGTERM);    Proc.WaitOnExit();....then it does actually work. I think I should look to be getting the PID of qcad-bin to be safe. ---------------------------------------------------------------------- MarkMLl · 2024-05-20 11:55 Quote from: petevick on May 20, 2024, 01:28:18 pm....then it does actually work. I think I should look to be getting the PID of qcad-bin to be safe. I'd not trust that +1 relationship if I were you, sooner or later it will clash with another process being started up by systemd or whatever. Frankly, as I've already said, I'd use killall for this. You're also likely to find that when you use that the outer wrapper will terminate automatically. I suggest you'll find something like this useful: Code: Text  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i ps faux | grep -B 5 -A 5 qcad-bin  MarkMLl ---------------------------------------------------------------------- petevick · 2024-05-20 15:27 After a lot of Googling and even a conversation with ChatGPT, I've finally got a rough, but working procedure, it does need a certain amount of checks adding, like empty strings etc, but I think it's a sound basis to work off. One other 'little' thing to throw in the mix, there could already be an existing Qcad process running that I have to avoid closing !!. Here's the code........... Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i procedure TWSplash.CloseQcadClick(Sender: TObject);{$IFDEF Linux}var  CProc: TProcess;  StrList: TStringList;  Str: String;  x: Integer = 0;{$ENDIF}  begin    {$IFDEF WINDOWS}    Form1.proc.Terminate(0);  // process created in the main form    {$ENDIF}    {$IFDEF Linux}    CProc:= TProcess.Create(nil);    StrList:= TStringList.Create;    CProc.Executable:= 'sh';    CProc.Parameters.Add('-c');    CProc.Parameters.Add('pgrep -f qcad-bin');    CProc.Options := CProc.Options + [poWaitOnExit, poUsePipes];    CProc.Execute;    StrList.LoadFromStream(CProc.Output);    x:= StrList.Count;    if x = 2 then Str:= StrList[0];    if x > 2 then Str:= StrList[1];    CProc.Free;    StrList.Free;    fpKill(StrToInt(Str), SIGTERM);    {$ENDIF}  end;One odd thing is that with one Qcad process running, typing 'pgrep -f qcad-bin' in the terminal gives one line of output, but the TProcess output gives two lines, I can't figure out what the second PID is. With two Qcad processes I know that the one I start in Lazarus is the second line of output. but as I say, it's all a bit rough and ready and needs lots of finessing. Many many thanks to  MarkMLI and TRon for your help and guidance. Also thanks to MarkMLI for giving me the word of the month, possibly year - fossicking ---------------------------------------------------------------------- MarkMLl · 2024-05-20 15:44 You're welcome, but I think you've got the idea that this is basically a Linux ** issue and you needed to look at how processes hung together. Once you know the pid of your qcad-bin, process, you should be able to work backwards through (lots of handwaving here) /proc to verify that it's one of your app's children. ** I almost put unix there. However I decided not to since there's quite a lot of variation in the way that ps and /proc behave across different unices: in particular between Linux and SunOS which as a member of the BSD clan probably means that I need to be careful about giving advice that e.g. Mac users might find misleading. MarkMLl ---------------------------------------------------------------------- petevick · 2024-05-20 19:00 Just to finalise this post, I've simplified the procedure somewhat, and also got rid of the mystery PID by removing the 'sh' command. The output is now purely a list of PID's for any qcad-bin processes only, the last in the list being the one I want to terminate...... Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i procedure TWSplash.CloseQcadClick(Sender: TObject);{$IFDEF Linux}var  CProc: TProcess;  StrList: TStringList;{$ENDIF}begin  {$IFDEF WINDOWS}  Form1.proc.Terminate(0);  {$ENDIF}  {$IFDEF Linux}  StrList:= TStringList.Create;  CProc:= TProcess.Create(nil);  try    with CProc do    begin      Executable:= 'pgrep';      Parameters.Add('-f');    Parameters.Add('qcad-bin');      Options := Options + [poWaitOnExit, poUsePipes];      Execute;      StrList.LoadFromStream(Output);    end;    if StrList.Count > 0 then      fpKill(StrToInt(StrList[StrList.Count-1]), SIGTERM)    else      CloseQcad.Visible:= False;  finally    CProc.Free;    StrList.Free;  end;  {$ENDIF}end;