Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / lazarus / 2014-10

TProcess.Input hangs

3 messages · 2 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Leonardo M. Ramé

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?

Leonardo M. Ram? Medical IT - Griensu S.A. Av. Col?n 636 - Piso 8 Of. A X5000EPT -- C?rdoba Tel.: +54(351)4246924 +54(351)4247788 +54(351)4247979 int. 19 Cel.: +54 9 (011) 40871877

Reply by email

Andrew Haines
to Leonardo M. Ramé
"Leonardo M. Ram?" wrote 28 lines
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

Reply by email

Leonardo M. Ramé
to Andrew Haines
Andrew Haines wrote 65 lines
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

Thanks Andrew!, that fixed the issue.

Reply by email