#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 Today 18:45:29

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

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

Board footer

Powered by FluxBB