[Lazarus] TProcess.Input hangs

Andrew Haines andrewd207 at aol.com
Sat Oct 18 01:54:36 CEST 2014


On 10/17/14 11:46, "Leonardo M. Ramé" wrote:
> Hi, I'm using this code to convert WAV files to MP3 on the fly, using
> lame. It was working great until today.
>
> It looks like this code has problems with large files sent to stdin.
>
> lProcess := TProcess.Create(nil);
> lProcess.Executable := '/usr/bin/lame';
> lProcess.Parameters.Add('-');  // stdin
> lProcess.Parameters.Add('-');  // stdout
> lProcess.Options := [poUsePipes];
> lProcess.Execute;
> lWav.LoadFromFile('/home/leonardo/16310.wav');
> lWav.Position:= 0;
> lWav.SaveToStream(lProcess.Input); // <--  here hangs
> lProcess.CloseInput;
>
>
> I also tried using this:
>
>   repeat
>     lReadCount := lProcess.Input.Write(lWav.Memory^, 500);
>     if lReadCount < 500 then
>       lReadCount := 0;
>   until lReadCount = 0;
>
> But also hangs before lReadCount < 500.
>
> Any hint?


You are writing to stdin while the process is generating data to stdout.
If you don't empty stdout and stderr the process will hang.

There's lots of info here:
http://wiki.freepascal.org/Executing_External_Programs

You need something like

while lProcess.Running or (lProcess.StdOut.NumBytesAvailable > 0) do
begin
  while lProcess.StdOut.NumBytesAvailable > 0 do
  begin
    lReadCount := lProcess.StdOut.Read(Buffer, SizeOf(Buffer);
    if lReadCount > 0 then
      // do something with encoded data
  end;

  // also you need to keep lProcess.StdErr empty or it can hang if it
gets full.
  while lProcess.StdErr.NumBytesAvailable > 0 do
  begin
    lReadCount := lProcess.StdErr.Read(Buffer, SizeOf(Buffer);
    if lReadCount > 0 then
      // do something with Stderr data
  end;

   // now write data to be encoded.
   lReadCount := lWav.Read(Buffer, SizeOf(Buffer));
   lProcess.Input.Write(Buffer, lReadCount);
end;

Regards,

Andrew Haines




More information about the Lazarus mailing list