strange behavior of Glib.Io.read_chars ?

Pierre Letouzey <[email protected]> Mon, 12 Nov 2012 17:36:18 +0100 (CET)
Newsgroups gmane.comp.lang.ocaml.lib.gtk
Message-ID <[email protected]>
Hi all

I'm currently playing with lablgtk, and especially trying its
asynchronous I/O abilities. All seem to work quite well when
I use Glib.Io.read inside a callback launched by Glib.Io.add_watch.
But while writing this code, I noticed in the gtk documentation
that g_io_channel_read is considered deprecated. So I tried
to use instead Glib.Io.read_chars, but to no avail : the whole
gtk app freezes forever when calling this function, even if
there's something to read on the channel. Am I missing something ?
Of course, I'm tempted to call that a bug, but my (labl)gtk
kungfu is still really weak, I may have goofed something.

Attached is a toy program demonstrating what I've tried and
the freeze I get. Compile with:

ocamlopt -o testgtkio -I +lablgtk2 unix.cmxa lablgtk.cmxa testgtkio.ml

then run it in a terminal, normally the button toggles every seconds.
Now type a newline in the terminal, and here everything freeze.
If read_chars is replaced by read, we get instead a pop-up telling
what have been read, and the button keeps on toggling.

I'm using debian stable (squeeze), hence ocaml 3.11.2, lablgtk2 2.14.0,
libgtk2 2.20, libglib 2.24.2, etc etc.

If that's indeed a bug, please let me know, I'll submit to the bug
tracker (with low priority since I'm quite happy with the
"use read instead of read_chars" pragmatic solution).

Greetings,
Pierre Letouzey

_______________________________________________
Lablgtk-list mailing list
[email protected]
https://lists.ocamlcore.org/cgi-bin/listinfo/lablgtk-list
testgtkio.ml (text/x-ocaml, 1.3 KB)
(* to compile with :
   ocamlopt -o testgtkio -I +lablgtk2 unix.cmxa lablgtk.cmxa testgtkio.ml *)

let all_conds = [ `ERR; `HUP; `IN; `NVAL; `PRI ] (* all but `OUT *)

let cond2string = function
  | `ERR -> "ERR"
  | `HUP -> "HUP"
  | `IN -> "IN"
  | `NVAL -> "NVAL"
  | `OUT -> "OUT"
  | `PRI -> "PRI"

let buf = String.make 1000 ' '

let inch = Glib.Io.channel_of_descr Unix.stdin

let stdin_reader conds =
  let condstr = String.concat ";" (List.map cond2string conds) in
  let msg =
    if List.mem `IN conds || List.mem `PRI conds then
      (* /!\ apparently, read_chars below is blocking, while read is ok *)
      let len = Glib.Io.read_chars inch buf 0 1000 in
      String.sub buf 0 len
    else ""
  in
  GToolbox.message_box ~title:"IN" (condstr ^ ":\n" ^ msg);
  true

let main () =
  let _ = GtkMain.Main.init () in
  let w = GWindow.window ~border_width:10 () in
  let b = GButton.toggle_button ~label:"Hello World" ~packing:w#add () in
  let _ = w#show ()
  in
  (* To visualize the freeze, we animate the button *)
  let r = ref false in
  let _ = Glib.Timeout.add ~ms:1000 ~callback:
    (fun () -> r := not !r; b#set_active !r; true)
  in
  (* Install the stdin reader *)
  let _ = Glib.Io.add_watch ~cond:all_conds ~callback:stdin_reader inch
  in
  GMain.Main.main ()

let _ = main ()