Welcome, Guest
Username: Password: Remember me
General Purpose Components and Libraries, discussions, problems and suggestions
  • Page:
  • 1

TOPIC:

TProcess Process.Input.Write() not functioning in Typhon since ver 8.21 6 days 4 hours ago #18897

  • Nino Luciani
  • Nino Luciani's Avatar Topic Author
  • Offline
  • New Member
  • New Member
  • Posts: 9
  • Thank you received: 1
Hi Guys

Not sure if this is the correct forum but;

I have an application that I wrote in mid 2022.
The app is designed for GNU/Linux. It uses TProcess to write to stdin of other processes.
The app requires some minor update and today, after a rebuild using the latest Typhon64 8.60, I discovered that
sending strings via TProcess to external process fails.
Don't know if something changed in later FPC or in Linux libs.

Details of system:
OS: Debian GNU/Linux 12 with latest updates

Code that no longer works since ver 8.21

//
//* Send data to process's STDIN //* nino 24-08-2022
//
if (_iList <> nil) and (_iList.Count > 0) then
begin
Strg := _iList.Text;

Process.Input.Write(Strg[1], Length(Strg));
Process.CloseInput();
end;
//

Full function code include:

//
//* If we don't know the size of the output, we cannot use poWaitOnExit.
//* On Linux the size of output pipe is 2 kB.
//* If the output data is more, we need to read the data.
//* This isn't possible if we are waiting, so we would get a deadlock here.
//* The Wait parameter default value is wsNoWait.
//* Use Wait = wsWait when you need to wait for a process with little output.
//*
//* CommandLine parameters are passed via [_pList]. One parameter per line please!
//*
//* Environment strings, as name/value pairs, are passed to the
//* executable via [_eList] if [_eList] if supplied.
//*
//* Data passed via [_iList] will be passed to the process's STDIN
//*
//* A temp Memorystream is used to buffer the output from STDOUT.
//* A temp Memorystream is used to buffer the output from STDERR.
//*
//* The buffer output is copied into [_sList] if [_sList] if supplied.
//*
//* If the command in [_CommandLine] causes an error, [_sList] will contain
//* the output that would normally go to STDERR.
//*
//* Returns True on command execution success (output from STDOUT)
//* Returns False on command execution failure (output from STDERR)
//
function ExecProcessEx(const _Executable : string; //* NL - 27 Oct 2022
_pList : TStringList = nil; //* CMD Line Param list
_sList : TStringList = nil; //* List to where the buffer output is copied
_eList : TStringList = nil; //* Environment strings to pass, as name/value pairs
_iList : TStringList = nil; //* Data to be passed to the process's STDIN
_Wait : TWaitState = wsNoWait) : Boolean;
const
READ_BYTES = 20480;

var
OutCount : LongInt;
ErrCount : LongInt;
OutBytesRead : LongInt;
ErrBytesRead : LongInt;
Done : Boolean;
Strg : string;
ProcessCMDLine : string;
Process : TProcess;
OutStream : TMemoryStream;
ErrStream : TMemoryStream;

begin
OutStream := TMemoryStream.Create();
ErrStream := TMemoryStream.Create();

try
OutBytesRead := 0;
ErrBytesRead := 0;

Process := TProcess.Create(nil);
try
ProcessCMDLine := _Executable; //* nino 14-05-2011

if _CheckIfShellRequired(ProcessCMDLine, _Executable) then
Process.CommandLine := ProcessCMDLine //* nino 24-10-2014
else
Process.Executable := _Executable;

//* Add Command Line Parameters
if _pList <> nil then
Process.Parameters := _pList; //* nino 27-10-2022

//* Set environment variables
if _eList <> nil then //* nino 13-06-2015
Process.Environment := _eList;

{$ifdef nl_debug}
Writeln(Process.CommandLine);
{$endif}

case _Wait of
wsWait : Process.Options := [poWaitOnExit, poUsePipes];
wsNoWait : Process.Options := [poUsePipes];
end; //* case.

try
//* Run the process.
Process.Execute();

//
//* Send data to process's STDIN //* nino 24-08-2022
//
if (_iList <> nil) and (_iList.Count > 0) then
begin
Strg := _iList.Text;

Process.Input.Write(Strg[1], Length(Strg));
Process.CloseInput();
end;
//

except
Result := False;
_sList.Clear();
_sList.Add('unknown process error [nl_exec.ExecProcessEx()]');
Exit;
end;

Done := False;

//* Accumulate all process output and/or error output.
while not Done do
begin
//* make sure we have room
OutStream.SetSize(OutBytesRead + READ_BYTES);
ErrStream.SetSize(ErrBytesRead + READ_BYTES);

//* try reading it.
OutCount := Process.Output.Read((OutStream.Memory + OutBytesRead)^, READ_BYTES);
ErrCount := Process.Stderr.Read((ErrStream.Memory + ErrBytesRead)^, READ_BYTES);

if OutCount > 0 then
Inc(OutBytesRead, OutCount);

if ErrCount > 0 then
Inc(ErrBytesRead, ErrCount);

if (OutCount = 0) and (ErrCount = 0) then
Done := True;
end;

OutStream.SetSize(OutBytesRead);
ErrStream.SetSize(ErrBytesRead);

//* Copy Stream into sList.
if _sList <> nil then
begin
Result := True;
_sList.LoadFromStream(OutStream);

//* if OutStream is empty, copy ErrStream into [_sList]
if _sList.Count = 0 then
begin
_sList.LoadFromStream(ErrStream);
Result := False;
end;
end;

finally
SafeFreeAndNil(Process);
end;

finally
SafeFreeAndNil(ErrStream);
SafeFreeAndNil(OutStream);
end;
end;

Please Log in or Create an account to join the conversation.

TProcess Process.Input.Write() not functioning in Typhon since ver 8.21 5 days 8 hours ago #18899

  • Matis A.
  • Matis A.'s Avatar
  • Away
  • Moderator
  • Moderator
  • Posts: 1194
  • Thank you received: 185
Thanks Sir
We are preparing the new LAB release of CT ver 8.70,
with a lot of work...

So, please, give us time to test your code and report here.
 
PilotLogic Core Programmer

Please Log in or Create an account to join the conversation.

Last edit: by Matis A..
  • Page:
  • 1