module Lwt_main: Uwt.Main
Analogue of Lwt_main
exception Main_error of error * string
Main_error is thrown, when uv_run returns an error - or if lwt doesn't report any result and libuv reports, that there are no pending tasks.
exception Fatal of exn * Printexc.raw_backtrace
You shouldn't raise exceptions, if you are using uwt. Always use
Lwt.fail
. If you throw exceptions nevertheless, uwt can
sometimes not propagate the exceptions to the OCaml runtime
immediately. This applies for example to exceptions that occur
inside iterative callbacks (like Stream.read_start
,
Timer.start
, Poll.start
, etc. ). They are passed to
Lwt.async_exception_hook
instead. If your Lwt.async_exception_hook
then also throws an exception, it is silently ignored.
However, uwt cannot catch all exceptions at the right
moment. Don't call any uwt function (especially Uwt.Main.run
) again,
if you catch such an exception below Uwt.Main.run
. A workaround is
currently not implemented, because only rare exceptions like
Out_of_memory
and Stackoverflow
are 'fatal' under rare
conditions - and they usually mean you are in unrecoverable
trouble anyway.
let rec main t1 =
match Uwt.Main.run t1 with
| exception Uwt.Main.Fatal(e,p) -> (* fatal, restart your process *)
log_fatal e p ; cleanup () ; exit 2
| exception x -> log_normal x ; main t3 (* safe *)
| result -> let y = ... (* no error *)
val yield : unit -> unit Lwt.t
yield ()
is a threads which suspends itself and then resumes
as soon as possible and terminates.
val run : 'a Lwt.t -> 'a
Unlike Lwt_main.run
, it's not allowed to nest calls to Uwt.Main.run.
The following code is invalid, an exception Main_error
will be thrown:
let help () =
let () = Uwt.Main.run foo in
Lwt.return_unit
in
Uwt.Main.run (help ())
And Uwt.Main.run
will complain about missing work (Main_error
again):
let s,t = Lwt.task () in
Uwt.Main.run s
With lwt.unix
the code above could lead to a busy loop (wasting your cpu
time - but it depends on the selected Lwt_engine).
If you really want your process to run forever, without waiting for any
I/O, you can create a Uwt.Timer.t
that gets called repeatedly, but does
nothing.
val enter_iter_hooks : (unit -> unit) Lwt_sequence.t
Functions that are called before the main iteration.
val leave_iter_hooks : (unit -> unit) Lwt_sequence.t
Functions that are called after the main iteration.
val exit_hooks : (unit -> unit Lwt.t) Lwt_sequence.t
Sets of functions executed just before the program exit.
Notes:
Don't use Pervasives.exit
together with uwt - or only use it outside any
function that is passed to Uwt.Main.run
. Pervasives.exit
interrupts the normal code flow and will leave libuv's internal
state in an inconsistent state. Your exit hooks will never be called.
val at_exit : (unit -> unit Lwt.t) -> unit
at_exit hook
adds hook at the left of exit_hooks
val cleanup : unit -> unit
Call Uwt.Main.cleanup
, if you've called Uwt.Main.run
and and don't intend to
call Uwt.Main.run
again any time soon. It will free some internally used
memory, but not all.