Reading/writing to stdio of running process/command does not work - reading blocks or is empty

,

Opening a prolog shell/repl process and sending strings to stdin and reading output doesn’t work. I don’t know what I am doing wrong but I tried a few methods and none of them seem to succeed. I just wanna run a long running prolog process and send some input prolog code, read the output, send some more, etc.
I would expect this to work but it does not:

julia> pb = IOBuffer();                                                                                                                                                       
                                                                                                                                                                              
julia> prolog_proc=open(`prolog`, pb;write=true)                                                                                                                              
Welcome to SWI-Prolog (threaded, 64 bits, version 9.0.4)                                                                                                                      
SWI-Prolog comes with ABSOLUTELY NO WARRANTY. This is free software.                                                                                                          
Please run ?- license. for legal details.                                                                                                                                     
                                                                                                                                                                              
For online help and background, visit https://www.swi-prolog.org                                                                                                              
For built-in help, use ?- help(Topic). or ?- apropos(Word).                                                                                                                   
                                                                                                                                                                              
Process(`prolog`, ProcessRunning)                                                                                                                                             
                                                                                                                                                                              
julia> prolog_proc                                                                                                                                                            
Process(`prolog`, ProcessRunning)                                                                                                                                             
                                                                                                                                                                              
julia> prolog_proc.                                                                                                                                                           
                                                                                                                                                                              
cmd         err                                                                                                                                                               
exitcode    exitnotify                                                                                                                                                        
handle      in                                                                                                                                                                
out         termsignal                                                                                                                                                        
julia> prolog_proc.exitcode                                                                                                                                                   
-9223372036854775808

julia> write(prolog_proc, "consult(\"hhlighthouse\").")
18

julia> String(read(pb))
""

julia> read(prolog_proc)
UInt8[]

julia> String(read(prolog_proc))
""

I also tried this simpler version but no dice so far:

julia> p = open(`prolog`; read=true, write=true)
Welcome to SWI-Prolog (threaded, 64 bits, version 9.0.4)
SWI-Prolog comes with ABSOLUTELY NO WARRANTY. This is free software.
Please run ?- license. for legal details.

For online help and background, visit https://www.swi-prolog.org
For built-in help, use ?- help(Topic). or ?- apropos(Word).

Process(`prolog`, ProcessRunning)

julia> p
Process(`prolog`, ProcessRunning)

julia> p.in
Base.PipeEndpoint(RawFD(21) open, 0 bytes waiting)

julia> p.out
Base.PipeEndpoint(RawFD(22) open, 0 bytes waiting)

julia> write(p.in, "consult(\"hhlighthouse.pl\").")
27

julia> p.out
Base.PipeEndpoint(RawFD(22) open, 0 bytes waiting)

julia> p.in
Base.PipeEndpoint(RawFD(21) open, 0 bytes waiting)

I worked with chatGPT and got this to run but still things seem to block without any output:

function launch_prolog()
    # Start the Prolog process
    prolog_process = open(`swipl -q`, "r+")
    return prolog_process
end

function send_query(prolog_process::IO, query::String)
    # Send query to Prolog process
    println(prolog_process, query * ".")
end

function read_output(prolog_process::IO)
    # Read Prolog output
    output = String(readline(prolog_process))
    return output
end

function close_prolog(prolog_process::IO)
    # Close the Prolog process
    close(prolog_process)
end

# Main function
function main()
    prolog_process = launch_prolog()
    
    # Example queries
    queries = [
        "member(X, [1, 2, 3, 4, 5])",
        "append([1, 2], [3, 4], L)"
    ]
    
    for query in queries
        send_query(prolog_process, query)
        output = read_output(prolog_process)
        println("Query: $query")
        println("Output: $output")
    end
    
    close_prolog(prolog_process)
end

main()

The first query, "member(X, [1, 2, 3, 4, 5])." produces output without a newline, i.e. just X = 1 . So your readline waits indefinitely for the newline.

Thanks so much for the reply. Is there some way to read whatever is available in the buffer without worrying about newlines?
I tried this version but it still hangs…

function read_output(prolog_process::IO)
	# Read Prolog output
	raw_data = zeros(UInt8,10)
	readbytes!(prolog_process, raw_data, 10)
	output = String(raw_data)
    return output
end

What julia version aare you running? I tried 1.10.2 and 1.7 but I can’t see difference in behaviour.

nevermind, tried reading 4 bytes and it worked!!! Cheers! You ended my frustration! :slight_smile:

For reference: the original issue I was having is that I was failing to send a newline at the end of the prolog statement and there would be no output from prolog. In the gpt version the newline was being sent via “println” but reading was done with “readline” which wouldn’t work since prolog output did not include a newline. I think there’s some irony here.

2 Likes

There is a linux utility expect for such dialogs, I guess the authors also had some frustrations.

https://linux.die.net/man/1/expect

Thanks,
I use that when automating with bash scripts. The goal in this instance was to keep prolog session running and send things for processing then continuing in julia back and forth. Expect would also introduce another point of failure.