You are not logged in.
Pages: 1
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
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
Arnaud, let me bother you again this Sunday! ![]()
What's the best way to handle this issue?
Offline
@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.
see: mormot.core.os.pas#L6114-L6199
Let me know how its goes ![]()
edit: added a dedicated ffmpeg sample, you can read the tests project output there: https://pastebin.com/F57yWgHd
Last edited by flydev (2026-04-09 08:11:37)
Offline
@flydev — thank you, this is exactly what we needed!
Our use case: up to 8 concurrent FFmpeg capture processes (SDI decks via DeckLink), where we need to stop individual recordings gracefully while the others keep running. The current GenerateConsoleCtrlEvent approach kills the entire console group — all 8 decks go down.
Your TExternalProcess with proc.Write('q'#10) + WaitFor solves this cleanly. I tested the FFmpegDemo — the sibling isolation works perfectly (stopping Deck2 while Deck1 and Deck3 continue encoding).
The design as a standalone extension (mormot.ext.os) with zero patches to core is very practical — we can start using it right away.
And hopefully @ab considers including this into the main mORMot2 repository — IMHO it feels like a natural fit for mormot.core.os
We'll integrate this into our FeedIngest product and report back with results.
Great work on both Windows and Linux support!
Last edited by vs (Yesterday 12:16:12)
Offline
Pages: 1