I'm writing code to monitor the content of a file. When the program reaches the end of the the file I want it to terminate cleanly.
let log () : input_channel Lwt.t =
openfile "log" [O_RDONLY] 0 >>= fun fd ->
Lwt.return (of_fd input fd);;
let rec loop (ic: input_channel) = Lwt_io.read_line ic >>= fun text ->
Lwt_io.printl text >>= fun _ -> loop ic;;
let monitor () : unit Lwt.t = log () >>= loop;;
let handler : exn -> unit Lwt.t = fun e -> match e with
| End_of_file -> let (p: unit Lwt.t), r = Lwt.wait() in p
| x -> Lwt.fail x;;
let main () : unit Lwt.t = Lwt.catch monitor handler;;
let _ = Lwt_main.run (main ());;
However, when reading a file and reaching the end, the program does not terminate, it just hangs and I have to escape with Ctrl+c. I am not sure what is going on under the hood with bind but I figured whatever it's doing, eventually Lwt_io.readline ic should eventually hit the end of the file and return an End_of_file exception, which presumably would get passed over to the handler, etc.
If I had to guess at a resolution, I would think maybe in the last bind of the definition of >>= I would include some if check. But I'd be checking, I think, whether Lwt_io.read_line returned End_of_file, which I though should be handled by the handler.
The Lwt.wait function creates a promise which could only be resolved using the second element of the returned pair, basically, this function will never terminate:
let never_ready () =
let (p,_) = Lwt.wait in
p
and this is exactly what you've written.
Concerning a graceful termination, ideally, you should do this in the loop function so that you can close the channel and prevent leaking of the valuable resources, e.g.,
let rec loop (ic: input_channel) =
Lwt_io.read_line ic >>= function
| exception End_of_file ->
Lwt.close ic
| text->
Lwt_io.printl text >>= fun () ->
loop ic
The minimum change to your code would be, however, to use Lwt.return () instead of Lwt.wait in the body of your handler.
Related
I have the following code block which I modified from the mirageOS github repo:
open Lwt.Infix
module Main (KV: Mirage_kv.RO) = struct
let start kv =
let read_from_file kv =
KV.get kv (Mirage_kv.Key.v "secret") >|= function
| Error e ->
Logs.warn (fun f -> f "Could not compare the secret against a known constant: %a"
KV.pp_error e)
| Ok stored_secret ->
Logs.info (fun f -> f "Data -> %a" Format.pp_print_string stored_secret);
in
read_from_file kv
end
This code reads data from a file called "secret" and outputs it once. I want to read the file and output from it constantly with sleep in between.
The usage case is this: While this program is running I will update the secret file with other processes, so I want to see the change in the output.
What I tried ?
I tried to put the last statement in while loop with
in
while true do
read_from_file kv
done
But It gives the error This expression has type unit Lwt.t but an expression was expected of type unit because it is in the body of a while loop.
I just know that lwt is a threading library but I'm not a ocaml developer and don't try to be one, (I'm interested in MirageOS) , so I can't find the functional syntax to write it.
You need to write the loop as a function. e.g.
let rec loop () =
read_from_file kv >>= fun () ->
(* wait here? *)
loop ()
in
loop ()
I'm creating a chat server, and I have a function that handles login. There exists a preset ref called nick and a preset input stream imp. My code is as follows:
let handle_login nr (inp,outp) =
Lwt_io.printl "<Enter your 'nick'name>" >>= Lwt.return(nick := (Lwt_io.read_line inp))
However, this code give me the error:
Error: This expression has type string Lwt.t
but an expression was expected of type string.
I know that the following code does work:
let handle_login nr (inp,outp) =
Lwt_io.printl "<Enter your 'nick'name>" >>= Lwt.return(nick := "Jane")
In short, I don't know how to assign vars to values obtained from threads.
I'm not very familiar with Lwt, but if it works like any other monad I would think this should work:
let handle_login nr (inp, outp) =
Lwt_io.printl "<Enter your 'nick'name>"
>>= fun () -> Lwt_io.read_line inp
>>= fun str -> Lwt.return (nick := str)
But I have to point out as well that mutating shared state from async code is a disaster waiting to happen. That you can do it certainly doesn't mean you should.
I'd like to interrupt a call if it takes too long to compute, like this
try
do_something ()
with Too_long -> something_else ()
Is it possible to do something like that in OCaml? The function do_something may not be modified.
In general the only way to interrupt a function is to use a signal, as Basile suggested. Unfortunately the control flow will be transferred to a signal handler, so that you will be unable to return a value that you like. To get a more fine-grained control, you can run you do_something in separate thread. A first approximation would be the following function:
exception Timeout
let with_timeout timeout f =
let result = ref None in
let finished = Condition.create () in
let guard = Mutex.create () in
let set x =
Mutex.lock guard;
result := Some x;
Mutex.unlock guard in
Mutex.lock guard;
let work () =
let x = f () in
set x;
Condition.signal finished in
let delay () =
Thread.delay timeout;
Condition.signal finished in
let task = Thread.create work () in
let wait = Thread.create delay () in
Condition.wait finished guard;
match !result with
| None ->
Thread.kill task;
raise Timeout
| Some x ->
Thread.kill wait;
x
The solution with threads as well as with signal function has some drawbacks. For example, threads are switched in OCaml in specific iterruption points, in general this is any allocations. So if your code doesn't perform any allocations or external calls, then it may never yield to other thread and will run forever. A good example of such function is let rec f () = f (). In this is your case, then you should run your function in another process instead of thread. There're many libraries for multiprocessing in OCaml, to name a few:
parmap
forkwork
async-parallel
lwt-parallel
There is no built-in facility to perform this precise operation in the standard library, but it is rather straightforward to implement. Using the Thread module, run one thread to perform your main program and a monitoring thread that will kill the program if it lasts too long. Here is a starting implementation:
type 'a state =
| Running
| Finished of 'a
| Failed of exn
| Cancelled of 'a
let bounded_run d f g x =
let state = ref Running in
let p = ref None in
let m = ref None in
let cancel t' = match !t' with
| Some(t) -> Thread.kill t
| None -> ()
in
let program () =
(try state := Finished(f x)
with exn -> state := Failed (exn));
cancel m;
in
let monitor () =
Thread.delay d;
match !state with
| Running -> cancel p; state := Cancelled(g x)
| _ -> ()
in
p := Some(Thread.create program ());
m := Some(Thread.create monitor p);
(match !m with
| None -> ()
| Some(t) -> Thread.join t);
!state
The call bounded_run d f g x runs f x for at most d seconds and returns Finished(f x) if the computation runs in the given time. It might return Failed(exn) if the computation throws an exception. When the computation lasts too long, the returned value is Cancelled(g x).
This implementation has many defaults, for instance, the state and the returned values should have different types (the value Running should not be possible in the returned type), it does not use mutexes to prevent concurrent accesses to the p and m variables holding references to the threads we use. While it is rough at the edges, this should get you started, but for more advanced usage, you should also learn Event or 3rd party libraries such as Lwt or Async – the former will require you to change your function.
(I guess that you are on Linux)
Read more about signal(7)-s. You could use Ocaml's Sys.signal for Sys.sigalarm and Unix module (notably Unix.setitimer)
I'm trying to write a function that tries to evaluate a function, but stops after a specific timeout.
I tried to use Deferred.any, which returns a deferred that is fulfilled when one of the underlying deferred is fulfilled.
type 'a output = OK of 'a | Exn of exn
let fun_test msg f eq (inp,ans) =
let outp = wait_for (Deferred.any
[ return (try OK (f inp) with e -> Exn e)
; (after (Core.Std.sec 0.0) >>| (fun () -> Exn TIMEOUT))])
in {msg = msg;inp = inp;outp = outp;ans = ans;pass = eq outp ans}
I was not sure how to extract a value from the deferred monad, so I wrote a function 'wait_for' which just spins until the underlying value is determined.
let rec wait_for x =
match Deferred.peek x with
| None -> wait_for x
| Some done -> done;;
This did not work. After reading through the Async chapter of Real World OCaml, I realized I needed to start the scheduler. However I'm not sure where I would call Schedule.go in my code. I do not see where the type go : ?raise_unhandled_exn:bool -> unit -> Core.Std.never_returns would fit into code where you actually want your asynchronous code to return. The documentation for go says "Async programs do not exit until shutdown is called."
I was beginning to doubt I had taken the entirely wrong approach to the problem until I found a very similar solution to that same problem on this Cornell website
let timeout (thunk:unit -> 'a Deferred.t) (n:float) : ('a option) Deferred.t
= Deferred.any
[ after (sec n) >>| (fun () -> None) ;
thunk () >>= (fun x -> Some x) ]
Anyway, I'm not quite sure my use of wait_for is correct. Is there a canonical way to extract a value from the deferred monad? Also how do I start the scheduler?
Update:
I tried writing a timeout function using only Core.Std.Thread and Core.Std.Mutex.
let rec wait_for lck ptr =
Core.Std.Thread.delay 0.25;
Core.Std.Mutex.lock lck;
(match !ptr with
| None -> Core.Std.Mutex.unlock lck; wait_for lck ptr
| Some x -> Core.Std.Mutex.unlock lck; x);;
let timeout t f =
let lck = Core.Std.Mutex.create () in
let ptr = ref None in
let _ = Core.Std.Thread.create
(fun () -> Core.Std.Thread.delay t;
Core.Std.Mutex.lock lck;
(match !ptr with
| None -> ptr := Some (Exn TIMEOUT)
| Some _ -> ());
Core.Std.Mutex.unlock lck;) () in
let _ = Core.Std.Thread.create
(fun () -> let x = f () in
Core.Std.Mutex.lock lck;
(match !ptr with
| None -> ptr := Some x
| Some _ -> ());
Core.Std.Mutex.unlock lck;) () in
wait_for lck ptr
I think this is pretty close to working. It works on computations like let rec loop x = print_string ".\n"; loop x, but it does not work on computations like let rec loop x = loop x. I believe the problem right now is that if the computation f () loops infinitely, then its thread is never preempted, so none of other threads can notice the timeout has expired. If the thread does IO like printing a string, then the thread does get preempted. Also I don't know how to kill a thread, I couldn't find such a function in the documentation for Core.Std.Thread
The solution I came up with is
let kill pid sign =
try Unix.kill pid sign with
| Unix.Unix_error (e,f,p) -> debug_print ((Unix.error_message e)^"|"^f^"|"^p)
| e -> raise e;;
let timeout f arg time default =
let pipe_r,pipe_w = Unix.pipe () in
(match Unix.fork () with
| 0 -> let x = Some (f arg) in
let oc = Unix.out_channel_of_descr pipe_w in
Marshal.to_channel oc x [];
close_out oc;
exit 0
| pid0 ->
(match Unix.fork () with
| 0 -> Unix.sleep time;
kill pid0 Sys.sigkill;
let oc = Unix.out_channel_of_descr pipe_w in
Marshal.to_channel oc default [];
close_out oc;
exit 0
| pid1 -> let ic = Unix.in_channel_of_descr pipe_r in
let result = (Marshal.from_channel ic : 'b option) in
result ));;
I think I might be creating two zombie processes with this though. But it is the only solution that works on let rec loop x = loop x when compiled using ocamlopt (The solution using Unix.alarm given here works when compiled with ocamlc but not when compiled with ocamlopt).
I have a function save that take standard input, which is used individually like this:
./try < input.txt (* save function is in try file *)
input.txt
2
3
10 29 23
22 14 9
and now i put the function into another file called path.ml which is a part of my interpreter. Now I have a problem in defining the type of Save function and this is because save function has type in_channel, but when i write
type term = Save of in_channel
ocamlc complain about the parameter in the command function.
How can i fix this error? This is the reason why in my last question posted on stackoverflow, I asked for the way to express a variable that accept any type. I understand the answers but actually it doesn't help much in make the code running.
This is my code:
(* Data types *)
open Printf
type term = Print_line_in_file of int*string
| Print of string
| Save of in_channel (* error here *)
;;
let input_line_opt ic =
try Some (input_line ic)
with End_of_file -> None
let nth_line n filename =
let ic = open_in filename in
let rec aux i =
match input_line_opt ic with
| Some line ->
if i = n then begin
close_in ic;
(line)
end else aux (succ i)
| None ->
close_in ic;
failwith "end of file reached"
in
aux 1
(* get all lines *)
let k = ref 1
let first = ref ""
let second = ref ""
let sequence = ref []
let append_item lst a = lst # [a]
let save () =
try
while true do
let line = input_line stdin in
if k = ref 1
then
begin
first := line;
incr k;
end else
if k = ref 2
then
begin
second := line;
incr k;
end else
begin
sequence := append_item !sequence line;
incr k;
end
done;
None
with
End_of_file -> None;;
let rec command term = match term with
| Print (n) -> print_endline n
| Print_line_in_file (n, f) -> print_endline (nth_line n f)
| Save () -> save ()
;;
EDIT
Error in code:
Save of in_channel:
Error: This pattern matches values of type unit
but a pattern was expected which matches values of type in_channel
Save of unit:
Error: This expression has type 'a option
but an expression was expected of type unit
There are many errors in this code, so it's hard to know where to start.
One problem is this: your save function has type unit -> 'a option. So it's not the same type as the other branches of your final match. The fix is straightforward: save should return (), not None. In OCaml these are completely different things.
The immediate problem seems to be that you have Save () in your match, but have declared Save as taking an input channel. Your current code doesn't have any way to pass the input channel to the save function, but if it did, you would want something more like this in your match:
| Save ch -> save ch
Errors like this suggest (to me) that you're not so familiar with OCaml's type system. It would probably save you a lot of trouble if you went through a tutorial of some kind before writing much more code. You can find tutorials at http://ocaml.org.