Recent

Author Topic: TProcess.Execute behavior  (Read 12635 times)

Leledumbo

  • Hero Member
  • *****
  • Posts: 8108
  • Programming + Glam Metal + Tae Kwon Do = Me
Re: TProcess.Execute behavior
« Reply #15 on: September 10, 2015, 08:32:55 am »
1. What's the difference between ExitStatus and ExitCode within FreePascal? Why ExitStatus and not ExitCode?
2. The pascal code I'm interested should be used to build crossplatform binaries that call external applications. Is ExitStatus safer than ExitCode for this purpose?
As how the two are documented:
http://www.freepascal.org/docs-html/3.0.0/fcl/process/tprocess.exitstatus.html
http://www.freepascal.org/docs-html/3.0.0/fcl/process/tprocess.exitcode.html


Zoran

  • Hero Member
  • *****
  • Posts: 1459
    • http://wiki.lazarus.freepascal.org/User:Zoran
Re: TProcess.Execute behavior
« Reply #16 on: September 10, 2015, 09:36:41 am »
1. What's the difference between ExitStatus and ExitCode within FreePascal? Why ExitStatus and not ExitCode?
2. The pascal code I'm interested should be used to build crossplatform binaries that call external applications. Is ExitStatus safer than ExitCode for this purpose?
As how the two are documented:
http://www.freepascal.org/docs-html/3.0.0/fcl/process/tprocess.exitstatus.html
http://www.freepascal.org/docs-html/3.0.0/fcl/process/tprocess.exitcode.html

This does not make sense (from the first link you provided - ExitStatus):
Quote
The value of this property is only meaningful when the process is no longer running. If it is not running then the value is zero.


Leledumbo

  • Hero Member
  • *****
  • Posts: 8108
  • Programming + Glam Metal + Tae Kwon Do = Me
Re: TProcess.Execute behavior
« Reply #17 on: September 10, 2015, 10:12:41 am »
This does not make sense (from the first link you provided - ExitStatus):
Could you elaborate more? I think it does. That's exactly what $? shows after you execute an app.

Zoran

  • Hero Member
  • *****
  • Posts: 1459
    • http://wiki.lazarus.freepascal.org/User:Zoran
Re: TProcess.Execute behavior
« Reply #18 on: September 10, 2015, 10:38:40 am »
This does not make sense (from the first link you provided - ExitStatus):
Could you elaborate more? I think it does. That's exactly what $? shows after you execute an app.

So, when can this property be used?
The value of this property is only meaningful when the process is no longer running. => we can't use it when the process is running.
If it is not running then the value is zero. => we can't use it when the process is not running, it is always zero.

When is it meaningful to check this value? Never, according to documentation.
« Last Edit: September 10, 2015, 10:40:17 am by Zoran »

molly

  • Hero Member
  • *****
  • Posts: 2345
Re: TProcess.Execute behavior
« Reply #19 on: September 10, 2015, 01:04:36 pm »
Quote
When is it meaningful to check this value? Never, according to documentation.
Then you most certainly must have overlooked the situation were the command stopped working and you need to know _why_ it stopped working (as in lagprogramming's case).

Thanks for the links Leledumbo, as the current online docs doesn't mention exitcode.
« Last Edit: September 10, 2015, 01:16:20 pm by molly »

Leledumbo

  • Hero Member
  • *****
  • Posts: 8108
  • Programming + Glam Metal + Tae Kwon Do = Me
Re: TProcess.Execute behavior
« Reply #20 on: September 10, 2015, 02:56:10 pm »
So, when can this property be used?
The value of this property is only meaningful when the process is no longer running. => we can't use it when the process is running.
If it is not running then the value is zero. => we can't use it when the process is not running, it is always zero.

When is it meaningful to check this value? Never, according to documentation.
Note "When the process is no longer running". Certainly there's no exit status before the process is terminated, you can't use it while it's running. Wait until terminated (not Running = true) then you have the expected value.
Code: [Select]
p.Options := [poWaitOnExit];
p.Execute;
DoSomethingWith(p.ExitStatus); // <- there you have it correct

Basile B.

  • Guest
Re: TProcess.Execute behavior
« Reply #21 on: September 10, 2015, 04:49:12 pm »
Also, important detail:

if poUsePipes and poWaitOnExit are both set, the process won't return until the whole output is read.

In the wiki it's even recommended not to use the two options together if the output size is large because in this case poWaitOnExit locks the proc and it never returns... (instead use a while proc.active do {read/sleep/etc}; loop):o

Any comment about that ?
« Last Edit: September 10, 2015, 04:51:55 pm by BBasile »

Zoran

  • Hero Member
  • *****
  • Posts: 1459
    • http://wiki.lazarus.freepascal.org/User:Zoran
Re: TProcess.Execute behavior
« Reply #22 on: September 11, 2015, 07:22:24 am »
Note "When the process is no longer running". Certainly there's no exit status before the process is terminated, you can't use it while it's running. Wait until terminated (not Running = true) then you have the expected value.
Code: [Select]
p.Options := [poWaitOnExit];
p.Execute;
DoSomethingWith(p.ExitStatus); // <- there you have it correct
[/quote]

According to the documentation, you can put DoSomethingWith(0); in this example.
Note "If it is not running then the value is zero."  -- according to what documentation says, it is unconditionally zero. So, checking the value doesn't make sense.

Then you most certainly must have overlooked the situation were the command stopped working and you need to know _why_ it stopped working (as in lagprogramming's case).
How can you get the reason why, if the value is always zero, as documentation says?

Leledumbo

  • Hero Member
  • *****
  • Posts: 8108
  • Programming + Glam Metal + Tae Kwon Do = Me
Re: TProcess.Execute behavior
« Reply #23 on: September 11, 2015, 09:45:02 am »
According to the documentation, you can put DoSomethingWith(0); in this example.
Note "If it is not running then the value is zero."  -- according to what documentation says, it is unconditionally zero. So, checking the value doesn't make sense.
Either the documentation is too difficult for you to understand or you're just thinking too hard. I'll try to make it easier for you:

"When the process is no longer running" -> this means, the process was started before and at this point it has stopped / is no longer running.

"If it is not running then the value is zero" -> this means, the process hasn't even started and 0 indicates the initial value.

A simple demo might open your mind:
Code: [Select]
{$mode objfpc}{$H+}

uses
  Process;

function CreateProcessAndReturnExitStatus(Opts: TProcessOptions; const Param: String; const DoExecute: Boolean = true): Integer;
begin
  with TProcess.Create(nil) do begin
    Executable := 'fpc';
    Parameters.Add(Param);
    Options := Opts;
    if DoExecute then
      Execute;
    Result := ExitStatus;
    Free;
  end;
end;

begin
  WriteLn(CreateProcessAndReturnExitStatus([],'',false));                        //  0, because it's not executed at all
  WriteLn(CreateProcessAndReturnExitStatus([poUsePipes],'-h'));                  // -1, because it hasn't finished yet, provided that the ExitStatus returns before fpc -h itself
  WriteLn(CreateProcessAndReturnExitStatus([poUsePipes,poWaitOnExit],'-h'));     //  0, because it terminates successfully
  WriteLn(CreateProcessAndReturnExitStatus([poUsePipes,poWaitOnExit],'--help')); //  1, because it doesn't terminate successfully due to invalid option (1 is returned by fpc/ppcXXX)
end.
The -1 thing is kinda new to me, but at least what the documentation says is right.

Zoran

  • Hero Member
  • *****
  • Posts: 1459
    • http://wiki.lazarus.freepascal.org/User:Zoran
Re: TProcess.Execute behavior
« Reply #24 on: September 11, 2015, 01:47:01 pm »
According to the documentation, you can put DoSomethingWith(0); in this example.
Note "If it is not running then the value is zero."  -- according to what documentation says, it is unconditionally zero. So, checking the value doesn't make sense.
Either the documentation is too difficult for you to understand or you're just thinking too hard. I'll try to make it easier for you:

"When the process is no longer running" -> this means, the process was started before and at this point it has stopped / is no longer running.

"If it is not running then the value is zero" -> this means, the process hasn't even started and 0 indicates the initial value.

A simple demo might open your mind:
Code: [Select]
{$mode objfpc}{$H+}

uses
  Process;

function CreateProcessAndReturnExitStatus(Opts: TProcessOptions; const Param: String; const DoExecute: Boolean = true): Integer;
begin
  with TProcess.Create(nil) do begin
    Executable := 'fpc';
    Parameters.Add(Param);
    Options := Opts;
    if DoExecute then
      Execute;
    Result := ExitStatus;
    Free;
  end;
end;

begin
  WriteLn(CreateProcessAndReturnExitStatus([],'',false));                        //  0, because it's not executed at all
  WriteLn(CreateProcessAndReturnExitStatus([poUsePipes],'-h'));                  // -1, because it hasn't finished yet, provided that the ExitStatus returns before fpc -h itself
  WriteLn(CreateProcessAndReturnExitStatus([poUsePipes,poWaitOnExit],'-h'));     //  0, because it terminates successfully
  WriteLn(CreateProcessAndReturnExitStatus([poUsePipes,poWaitOnExit],'--help')); //  1, because it doesn't terminate successfully due to invalid option (1 is returned by fpc/ppcXXX)
end.
The -1 thing is kinda new to me, but at least what the documentation says is right.

Thank you.
However, I still think that documentation is wrong.
The documentation should be changed at least:
1. "When the process is no longer running" should be changed to "When the process has terminated successfully"
2. "If it's not running..." should be changed to "If the process hasn't started yet"

Plus, "If the process terminates unsuccessfully, 1 is returned." should be added.

I created a bug report about documentation: http://bugs.freepascal.org/view.php?id=28662