I'm using startProcess to communicate with a standalone module, but the input to and output from the module is out of sync with the calling program that catches the output.
I expect this:
Process started...
------------------------------------200
RCV:Test: 200
------------------------------------220
RCV:Test: 220
But instead I get this:
Process started...
------------------------------------200
------------------------------------220
RCV:Test: 200
RCV:Test: 220
I tried flushFile() on stdout thinking it might be buffered, but that didn't help. The behavior is different when using just readLine() directly or in a while hasData() loop, but it's still out of sync. This is compiled as nim c -mm:orc <file>. What am I doing wrong?
Main program
# startProcess test to show output of background process
import std/osproc
import std/os
import std/streams
import std/strutils
import std/strformat
import times
var
projectModule = "listenreply"
pModule: Process
pOut: Stream
pIn: Stream
pErr: Stream
proc pipeModule(message: string): string =
var catchOutput: string = ""
pIn.writeLine(message)
pIn.flush()
while hasData(pModule):
catchOutput = catchOutput & "\n" & pOut.readLine()
return catchOutput
proc loadModule(module: string) =
debugEcho("Starting process...")
pModule = startProcess(module, args = [""], options = {poUsePath}) #, poInteractive})
pOut = pModule.outputStream()
pIn = pModule.inputStream()
pErr = pModule.errorStream()
debugEcho("Process started...")
proc unloadModule(module: string) =
discard pModule.waitForExit(2000)
var exitCode = pModule.peekExitCode()
echo "exit code: ", exitCode
pModule.close()
when isMainModule:
try:
loadModule(projectModule)
var
text: string
sendTxt: string
catchOutput: string
sleeper: int = 500
counter: int = 0
if pModule.running():
for c in 0..20:
echo "------------------------------------", sleeper
catchOutput = pipeModule(fmt("Test:{sleeper:5d}"))
echo catchOutput
text = text & catchOutput & " "
sleep(sleeper)
sleeper += 20
echo "All catched output:", text
discard pipeModule("QUIT")
sleep(100)
while hasData(pModule):
catchOutput = catchOutput & "\n" & pOut.readLine()
echo catchOutput
echo "That were ", catchOutput.len, " bytes"
# try getting stderr output
sleep(1000)
echo "Going to test standard error read..."
echo "Data ?", hasData(pModule)
for i in 0..8:
var e: string = ""
try:
e = pErr.readLine()
except:
e = "no data"
echo(fmt("Error {i:02d}: {e}"))
unloadModule(projectModule)
else: #not running
echo "Process could not be started"
except Exception as e:
var error = getCurrentException()
echo error.msg
called program
# modifies input and writes to stdout/stderr to test nim startProcess
import os
import times
import std/strutils
import strformat
var
stopApp: bool = false
proc errorEcho*(x: varargs[string, `$`]) = {.noSideEffect.}:
# echo to standard error (lie to the compiler it has no side effects)
stderr.writeLine x
when isMainModule:
var line: string
while not stopApp:
line = stdin.readLine()
if line.startsWith("QUIT"):
stopApp = true
echo "QUIT RECEIVED\n"
errorEcho("TEST to standard error")
else:
stdout.writeLine("RECEIVED:" & line & "\n")
stdout.flushFile()
quit(0)