ocsigen / lwt_glib

GLib/GTK event loop for Lwt
Other
11 stars 3 forks source link

lwt_unix.sleep unexpectedly hangs when invoked inside a gtk callback #4

Open lebotlan opened 5 years ago

lebotlan commented 5 years ago

Hi,

Consider this piece of code (using lwt_ppx syntax) :

let tests () =
   Printf.printf "Before sleep.\n%!" ;
   let%lwt () = Lwt_unix.sleep 0.5 in
   Printf.printf "After sleep.\n%!" ;
   Lwt.return_unit

In order to use lwt code within a gtk callback, I use the (supposedly) canonical way to do this:

let cb _ =
    let () = Lwt.async tests in
    true

This callback is used, for instance, on an event_box (called 'zone') :

let _ = zone#event#connect#button_release ~callback:cb

Then, I observe the following behaviour: If I click in the zone (only click, the mouse must not move), the message "Before sleep" is printed. It hangs undefinitely, until I move the mouse (which generates a gtk event). Then, the message "After sleep" is displayed.

In short : Lwt_unix.sleep hangs until some arbitrary gtk event occurs.

_Note that if you use a button instead of an event box, the button generates at least one event after it has been clicked (most likely to redraw itself), hence the lwtunix.sleep does not block

A quick fix consists in adding a gtk timer :

let _ = GMain.Timeout.add ~ms:100 ~callback:(fun () -> true)

..but this is not really satisfactory.

Here is a zip exposing the bug. Requires dune, lablgtk, lwt_glib. Type 'make'.

(github does not support .tgz ??????)

Lwt_hangs.zip

aantron commented 5 years ago

I suggest to debug this by cloning this repo and pinning the checkout:

git clone https://github.com/ocsigen/lwt_glib.git
cd lwt_glib
opam pin add lwt_glib .

or, for faster debugging, uninstall lwt_glib in opam, then clone the repo into a Dune workspace, as a sibling of your project.

To start, I'd add a print to STDERR here, showing the timeout that is passed on each call to poll. Most likely, that is incorrect immediately after the sleep is submitted and the program drains other events and goes to "sleep," so it will be necessary to examine the code above that, or go up the call stack. It's also possible that the function is simply not being called correctly in some way. Relevant parts are:

If you hit any snags, including conceptual ones, please ask. I am quite rusty on GTK at this point. I can help much more on the Lwt end.

@let-def may also have some insight, having worked on this or similar code relatively recently.

lebotlan commented 5 years ago

Thanks for this piece of advice. I will try this when possible (not until a few months, most likely).