#1 2025-06-25 21:01:09

keinn
Member
Registered: 2014-10-20
Posts: 121

RunRedirect feature request(stdin)

The RunRedirect works very well for calling simple external commands, but it is also too simplistic.
In Python, there is a subprocess module that allows interaction with third-party processes via stdin/stdout — executing commands and retrieving their output.
This enables communication with programs like Python, Node.js, and others (I know there are solutions like Python4Delphi or SyNode, SpiderMonkey, but that's a different matter).
Maybe some JS engine like Chakaracore or QuickJS is more suitable for run js code , but the NodeJS module(ecosystem) is not something a pure engine can have.
the stdin/stdout pipe solution makes the program highly flexible and extensible (which is very important).

After a whole night of tracking and research, I found that we can easily implement this by making a few small modifications to our RunRedirect:

in RunCommandWin()

var
in_Rd,in_Wr:THandle;
...

//create a input pipe right after the output pipe
CreatePipe(In_rd, In_wr, @security, 0);
SetHandleInformation(In_wr, HANDLE_FLAG_INHERIT, 0);

//bind with process startupinfo 
startupinfo.hStdInput := In_rd;//GetStdHandle(STD_INPUT_HANDLE);

//write to stdInput after CreateProcessW sucess
const jsCode:RawUtf8='2+3'


  FileWriteAll(In_wr,Pointer(jsCode),length(jsCode));
  if Assigned(onoutput) then
    onoutput('', processinfo.dwProcessId);
 
//close In_wr
  if rd <> 0 then
  begin
    // wait and redirect - see https://stackoverflow.com/a/25725197/458259
    CloseHandle(In_wr);
    CloseHandle(wr);

....

this work sucess with nodejs.exe -i.

but i dont know how to do ,without break the mormot.core.os codebase, or make it crossplatform(maybe with Popen).

maybe we need a func like

function RunRedirect(const cmd: TFileName; Input:RawUtf8; exitcode: PInteger;
  const onoutput: TOnRedirect; waitfordelayms: cardinal; setresult: boolean;
  const env, wrkdir: TFileName; options: TRunOptions): RawByteString; 

Or even better: create a process using stdInput/stdOutput pipes, and allow external access to the process's stdInput and stdOutput handles.
eg:create process(or 10x process) with pipes then interact with it(them) at any time

This would enable more flexible interaction.

Last edited by keinn (2025-06-25 21:36:23)

Offline

#2 2026-03-12 18:45:29

vs
Member
Registered: 2019-10-21
Posts: 56

Re: RunRedirect feature request(stdin)

Re: RunRedirect feature request (stdin)

Adding another strong use-case for roKeepStdinPipe (or similar): graceful per-process stop of multiple FFmpeg instances.

We run N FFmpeg capture processes (one per deck, up to 8) via RunRedirect. When the operator stops one deck, we need to send q\n to that specific FFmpeg — the standard graceful shutdown signal. FFmpeg then flushes its buffers, closes the output file cleanly, and exits with code 0.

The current workaround — returning true from TOnRedirect — triggers GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0), which sends the signal to the entire console group. With 8 active FFmpeg processes this would kill all of them simultaneously. So we currently rely on TerminateProcess (hard kill after 5s), which risks incomplete/corrupted output files.

A roKeepStdinPipe flag that keeps the stdin write-handle accessible would allow writing q\n to the specific process and solve this cleanly. Alternatively, a roNewProcessGroup flag (CREATE_NEW_PROCESS_GROUP) would allow targeted GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT, pid).

Either approach would make RunRedirect suitable for production multi-process management.

---

Offline

#3 2026-03-22 14:18:22

vs
Member
Registered: 2019-10-21
Posts: 56

Re: RunRedirect feature request(stdin)

Arnaud, let me bother you again this Sunday! roll

What's the best way to handle this issue?

Offline

#4 Today 19:33:20

flydev
Member
From: France
Registered: 2020-11-27
Posts: 155
Website

Re: RunRedirect feature request(stdin)

@vs I needed the same features to test some ai automation flows. Try the branch "feat/stdin-pipe" from my fork. You'll find an "external-process" example in the ex folder that runs on both linux and windows. The example is based on your comments above. There are also tests, so you can compile it on windows and run both the tests and the sample.

FYI: the fork is based on mormot 2.4.14669 (current is 2.4.14720) - I still need to merge the latest commits from the synopse repo, as the version I used seems to cause a segfault when starting TSynDictionary tests on ubuntu (this issue is unrelated to the feature itself).

see: mormot.core.os.pas#L6114-L6199

Let me know how its goes smile

Last edited by flydev (Today 19:40:53)

Offline

Board footer

Powered by FluxBB