Problems communicating with a child process

I’ve have a hobby project, OCaml bindings to GTK4 which are not LablGTK. And to check the viability of the concept I wanted something more than a counter demo with 2 buttons. So I decided to port ocaml-top editor as a proof of concept. And I’ve run into a problem and maybe I can get some help with.

The probem. Here is the editor

Looks like it works and to a some degree it does. But, it does it in a very peculiar way.
When send the the code on the left side to OCaml in a child process for evaluation it only display the first line.

Then nothing happens. I press space a few times and I get the result of the first expression back. Then I press space more times and I get the result of the second expression. And so on.

After some debugging I’ve seen that after input is sent to but OCaml does not get it and sit in read(0, .. waiting.

Until I press a key once or more times.

Yes, I do call flush on channel, and yes using Unix.write does not help. Most probably some kind of bad interaction between GTK main loop and OCaml being single threaded.

Main question, basically is, if is there something obvious that I miss?

Start your program and attach a strace to both processes, with strace -p $pid, to follow the I/O. What’s most likely is that you should be using an I/O multiplexer, like Unix.select, but have instead some alternating read/write calls that cause one or the other program to block. Subtle protocol issues like this crop up all the time, especially in networking. Interactively it’s easy to treat stdin/stdout like completely unrelated I/O streams, but in IPC the other side can be waiting for you finish reading its last write() before it’ll accept more input.

It could be that your program is attending to GTK instead of reading from the subprocess, yeah. An easy way to check that is to have a separate Domain deal with the subprocess, communicating through Domainslib.Chan with the GTK side.

Well, I found the issue. I’m using g_application_run to initialize and start the program, because that’s what all the GTK docs are recommending and from the moment it starts until it ends the only chance OCaml code has to run is during callbacks. Which means the neither threads and IO will have a chance to run.

So I’ve added this before calling g_applicatin_run wrapper.

    let idle_fn = fun () -> Unix.sleepf 0.01; true in
    Idle.add idle_fn |> ignore;

So for now it solved my problem. Not in the best way, but it did.