* * *

Author Topic: TProcess.Output is permanently empty  (Read 2917 times)

TCH

  • Jr. Member
  • **
  • Posts: 75
TProcess.Output is permanently empty
« on: January 03, 2018, 11:48:10 pm »
I have a small C program which writes a 8-10 byte sized line to the stdout at roughly every 150-200 millisecond.

I have a Lazarus program what runs this program as a TProcess and tries to process it's output, but the Output pipe stream is always empty.

I create the process:
Code: Pascal  [Select]
  1. proc := TProcess.Create(nil);
  2. proc.Options := [poUsePipes];
  3. proc.CommandLine := '/usr/local/bin/cprog arg1 arg2 ';
  4. proctimer.Enabled := True;
And there is a timer which fires every 100 millisecond:
Code: Pascal  [Select]
  1. procedure TForm1.proctimerTimer(Sender: TObject);
  2. var
  3.         i, bc: integer;
  4.         buffer: array[0..15] of char;
  5. begin
  6.         bc := proc.Output.NumBytesAvailable;
  7.         proc.Output.read(buffer[0], bc);
  8.         i := 0;
  9.         while (i < bc) do
  10.         begin
  11.                 // process the incoming data
  12.         end;
  13. end;
And the variable bc is always zero, the Output pipe is always empty.

What's the problem with this code?

Jurassic Pork

  • Hero Member
  • *****
  • Posts: 680
Re: TProcess.Output is permanently empty
« Reply #1 on: January 04, 2018, 01:48:11 am »
hello,
have you forgotten the proc.Execute ?  :-X

And not sure that you can use a Timer.
Other solution use a loop like this for example :
Code: Pascal  [Select]
  1. procedure TForm1.Button9Click(Sender: TObject);
  2. var Proc: TProcess;
  3.            CharBuffer: array [0..511] of char;
  4.           ReadCount: integer;
  5. begin
  6. try
  7. Proc := TProcess.Create(nil);
  8. Proc.Options := [poUsePipes];
  9. Proc.CommandLine := '/bin/ping -c 5 127.0.0.1';
  10. Proc.Execute();
  11. while (Proc.Running) or (Proc.Output.NumBytesAvailable > 0) or
  12.        (Proc.Stderr.NumBytesAvailable > 0) do
  13.      begin
  14.        // read stdout and write to our stdout
  15.        while Proc.Output.NumBytesAvailable > 0 do
  16.        begin
  17.          ReadCount := Min(512, Proc.Output.NumBytesAvailable); //Read up to buffer, not more
  18.          Proc.Output.Read(CharBuffer, ReadCount);
  19.          Memo1.Lines.Append(Copy(CharBuffer, 0, ReadCount));
  20.        end;
  21.        // read stderr and write to our stderr
  22.        while Proc.Stderr.NumBytesAvailable > 0 do
  23.        begin
  24.          ReadCount := Min(512, Proc.Stderr.NumBytesAvailable); //Read up to buffer, not more
  25.          Proc.Stderr.Read(CharBuffer, ReadCount);
  26.           Memo1.Lines.Append(Copy(CharBuffer, 0, ReadCount));
  27.        end;
  28.         application.ProcessMessages;
  29.         sleep(200);
  30.      end;
  31.      ExitCode := Proc.ExitStatus;
  32.    finally
  33.      Proc.Free;
  34.    end;
  35. end;

Friendly, J.P

TCH

  • Jr. Member
  • **
  • Posts: 75
Re: TProcess.Output is permanently empty
« Reply #2 on: January 04, 2018, 05:57:32 pm »
have you forgotten the proc.Execute ?  :-X

Only in my example code, not in the real one of course.

Code: Pascal  [Select]
  1.         application.ProcessMessages;
  2.         sleep(200);
This is practically what a TTimer does: do its job, let the GUI do its, then waits for some time.
And reading from the Output is working with TTimer-s, i already did it before; for example this program does it and works.

I think, the C program outputs its output too slow; i did another program, which just omits garbage to the console with much more speed and the Pascal code suddenly begun to work. But the one which only prints out data after 150-200 ms will give an empty Output buffer.
« Last Edit: January 04, 2018, 06:08:37 pm by TCH »

Thaddy

  • Hero Member
  • *****
  • Posts: 5760
Re: TProcess.Output is permanently empty
« Reply #3 on: January 04, 2018, 06:05:19 pm »
Don't use the timer. that's silly. Use TAsyncProcess if you are not satisfied, The timer will get you into trouble at one time. Timers are for timing, not to solve sync problems. That's bad programming. Delay and Sleep are too...
Sync doesn't rely on timing: it is unpredictable by nature.
« Last Edit: January 04, 2018, 06:07:57 pm by Thaddy »
recommends {$macro on}{$define Silly:=ObjFpc}

TCH

  • Jr. Member
  • **
  • Posts: 75
Re: TProcess.Output is permanently empty
« Reply #4 on: January 04, 2018, 06:22:06 pm »
I don't care how i can use, but i need to run this program along with mine because it's outputs are determining what my program should do.
If i cannot use TTimer and sleep / delay then what should i do? A TThread would also need some timing, or else it would consume all CPU time.

Thaddy

  • Hero Member
  • *****
  • Posts: 5760
Re: TProcess.Output is permanently empty
« Reply #5 on: January 04, 2018, 06:23:46 pm »
Use TAsynchProcess. And - of course - a timeout value, but chosen so high it should never occur, like 1 whole second.

Just curious: can you solve this in C.... :D :D :D :D Does the C code have a timer?  8-) >:D :P
Well then,write it in Pascal syntax.....

You may need some lessons in blocking vs non-blocking code but then file this under beginners.
« Last Edit: January 04, 2018, 06:36:13 pm by Thaddy »
recommends {$macro on}{$define Silly:=ObjFpc}

TCH

  • Jr. Member
  • **
  • Posts: 75
Re: TProcess.Output is permanently empty
« Reply #6 on: January 04, 2018, 06:33:51 pm »
I replaced the declarations to TAsynchProcess nothing has changed.

Solve what in C? I did not wrote the C program, i just have to use it.

Thaddy

  • Hero Member
  • *****
  • Posts: 5760
Re: TProcess.Output is permanently empty
« Reply #7 on: January 04, 2018, 06:39:37 pm »
read my last remark - that crossed your answer -.
Forget about in what language the program you are communicating with is written in. That does not matter at all. You are trying to get reliable communication between yours and some other program. Right?
If I am right I will help you further. If the program or process written in C or whatever behaves well and writes to pipes or stdout we can fix this (without a timer)
« Last Edit: January 04, 2018, 06:42:58 pm by Thaddy »
recommends {$macro on}{$define Silly:=ObjFpc}

TCH

  • Jr. Member
  • **
  • Posts: 75
Re: TProcess.Output is permanently empty
« Reply #8 on: January 04, 2018, 06:48:32 pm »
Okay, so what should i do? I just rewrote it to use a TThread with sleep instead of TTimer and it still does not work.

Thaddy

  • Hero Member
  • *****
  • Posts: 5760
Re: TProcess.Output is permanently empty
« Reply #9 on: January 04, 2018, 06:54:02 pm »
Then we/I need some code first.. (Don't worry,I am outspoken but harmless)
recommends {$macro on}{$define Silly:=ObjFpc}

TCH

  • Jr. Member
  • **
  • Posts: 75
Re: TProcess.Output is permanently empty
« Reply #10 on: January 04, 2018, 07:07:34 pm »
The example code is in the opening post. I cannot give you the real code, since it's company code and it's not mine.

The basic idea is just this: An external program dumps out a line with some chars every 150-200 ms to the stdout. I already have a Pascal program which does a lot of thing, but among them, i need to track these written lines. The starting/stopping/etc. of the external program works just fine, but the Output buffer is always empty.

Thaddy

  • Hero Member
  • *****
  • Posts: 5760
Re: TProcess.Output is permanently empty
« Reply #11 on: January 04, 2018, 07:09:33 pm »
Ok, will have a look. Have to eat first.
recommends {$macro on}{$define Silly:=ObjFpc}

TCH

  • Jr. Member
  • **
  • Posts: 75
Re: TProcess.Output is permanently empty
« Reply #12 on: January 04, 2018, 07:14:49 pm »
Приятного аппетита!

Leledumbo

  • Hero Member
  • *****
  • Posts: 7845
  • Programming + Glam Metal + Tae Kwon Do = Me
Re: TProcess.Output is permanently empty
« Reply #13 on: January 04, 2018, 10:44:48 pm »
As you have abstracted the actual program and parameters, and not willing to give small, compilable and runnable program that demonstrates the behavior, I cannot really know what is wrong so this is just a wild guess.

CommandLine is deprecated, use Executable and Parameters to form the command to execute. Improper quoting is enough to ruin everything.
Are you sure that the process is even executing? Perhaps it stops already? Check Running and ExitStatus property.

TCH

  • Jr. Member
  • **
  • Posts: 75
Re: TProcess.Output is permanently empty
« Reply #14 on: January 04, 2018, 10:56:55 pm »
The C program is closed, so i cannot even give the source of it. As for the Pascal, as i said, it's not mine, i cannot distribute the sources.

The external program is running fine, it communicates via serial port and i see the LED blinking. If the programs tops, the LED stops blinking. And it does not matter if i use CommandLine or the new methods, i've checked the parameters and all is fine...

 

Recent

Get Lazarus at SourceForge.net. Fast, secure and Free Open Source software downloads Open Hub project report for Lazarus