3

Here is a simple program that uses the Unix module to interact with a subprocess. I just launch a cat shell command, send it a string and read it back:

#load "unix.cma";; (* Needed if you are in the toplevel *)

let () =
    let sin, sout, serr = Unix.open_process_full "cat" [||]  in
    output_string sout "test\n";
    flush sout;
    input_line sin |> print_string;
    flush stdout;
    Unix.close_process_full (sin, sout, serr) |> ignore;;

Recently I started studying the Lwt library, and I wanted to reproduce the same functionality with it. I though that the following should have exactly the same result:

    #use "topfind";;                (*                            *)
    #thread;;                       (* Also only for the toplevel *)
    #require "lwt.simple-top";;     (*                            *)

    let () =
        let open Lwt in
        let process = Lwt_process.open_process_full ( "cat" , [||]  ) in
        Lwt_io.write_line process#stdin "test\n"
        >>= ( fun ()  -> Lwt_io.flush process#stdin  )
        >>= ( fun ()  -> Lwt_io.read  process#stdout )
        >>= ( fun str -> Lwt_io.print str            )
        >>= ( fun ()  -> Lwt_io.flush Lwt_io.stdout  )
        |> Lwt_main.run

But it doesn't work as I expect it to -- apparently it reads and then prints an empty string.

I guess I have some fundamental confusion on how Lwt should work, but I cannot figure it out. Can someone show me how one can communicate with a subprocess using Lwt?

Kostya
  • 1,072
  • 11
  • 24
  • You're passing it incorrectly: Need something like: `Lwt_process.open_process_full ("cat", [|"cat"; "Makefile"|])` –  Mar 21 '16 at 19:47
  • @EdgarAroutiounian he's running `cat` with no arguments so it will copy stdin to stdout (of `cat`.) – RichN Mar 21 '16 at 19:50
  • @EdgarAroutiounian Yeah `[|"cat"; "Makefile"|]` works and dumps the Makefile. But that is not what I want -- as @RichN said, I'd like to use `cat` as stdin -> stdout program. I also tried `[|"cat"|]` -- that blocks the program for some bizarre reason... – Kostya Mar 21 '16 at 19:59

1 Answers1

2

Use Lwt_process.shell to make a proper command, in your case, the proper command is the following:

Lwt_process.shell "cat";;
- : Lwt_process.command = ("", [|"/bin/sh"; "-c"; "cat"|])

Also, I suspect, that after you will run your program in a proper way, you will be wondering, why is your program blocking. This reason is because cat process will not finish until you write an EOF to it's input channel. That's why the Lwt_io.read call will not ever finish. A solution would be to close the stdin channel.

ivg
  • 34,431
  • 2
  • 35
  • 63