caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
* [Caml-list] try...finally , threads, stack-tracebacks .... in ocaml
@ 2013-04-10 22:16 Chet Murthy
  2013-04-10 22:28 ` simon cruanes
                   ` (2 more replies)
  0 siblings, 3 replies; 14+ messages in thread
From: Chet Murthy @ 2013-04-10 22:16 UTC (permalink / raw)
  To: Caml List


People have previously asked about try...finally support in Ocaml, and
it's been observed (correctly) that you can write a little combinator
to give you this support, e.g.

let finally f arg finf =
  let rv = try Inl(f arg) with e ->
    Inr e
  in (try finf arg rv with e -> ());
	match rv with
		Inl v -> v
	  | Inr e -> raise e

The problem is, you discard stack-traceback when you rethrow the
exception.  One can program around this explicitly by capturing the
backtrace string and appending it to the rethrown exception, but it's
cumbersome and won't work for exceptions like Not_found that are
already defined without a mutable string slot.

It sure would be nice of ocaml had try...finally that preserved the
traceback information properly .... though maybe it isn't possible.
Certainly in the case where the finally block doesn't raise any
exceptions itself (even those that are caught silently), it seems like
it ought to be possible.

In an unrelated but similar sense, when programming with threads in
ocaml, it's easy (easy!) to deadlock your program.  Now, I've been
writing Java programs for years, and so am aware of how careful one
must be, and I'm writing my code using a single mutex protecting the
critical section.  But I forgot and didn't mutex-protect one method --
what merely printed out the contents of a shared daa-structure, and
when that printout coincided with a thread actually mutating the
data-structure, I got a deadlock.  Not hard to track down, and I
chided myself for being lax.

But the thing is, in Java (blecch!) I would have been able to use the
"javacore" facility to get a full-thread stack-traceback, and could
have used that to get a good idea of where my deadlock was.

I'm not saying that this is something ocaml should have, but I figured
I'd ask: are others (who use threads in ocaml) wishing for something
like this?

--chet--



^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [Caml-list] try...finally , threads, stack-tracebacks .... in ocaml
  2013-04-10 22:16 [Caml-list] try...finally , threads, stack-tracebacks .... in ocaml Chet Murthy
@ 2013-04-10 22:28 ` simon cruanes
  2013-04-11  0:19   ` Francois Berenger
  2013-04-10 23:35 ` Yaron Minsky
  2013-04-11  6:25 ` Jacques-Henri Jourdan
  2 siblings, 1 reply; 14+ messages in thread
From: simon cruanes @ 2013-04-10 22:28 UTC (permalink / raw)
  To: caml-list

An interesting solution for the safe resource acquisition/release, I
believe, is the Go statement "defer" [1]. In OCaml, you would write
something like:

let my_fun () =
  Mutex.lock some_lock;
  defer (fun () -> Mutex.unlock some_lock);
  (* critical section to the end of the block *)
  ....
  let final_result = 42 in
  final_result   (* returns, but runs defer-ed statements first *)

In case an exception is thrown before the function returns, defer-ed
statements would still be executed, before the exception is raised again
(with the full stacktrace). Defer-ed statements are executed in the
reverse order of their definitions. It also works for resources like
files, sockets, etc.

Simon

[1] http://blog.golang.org/2010/08/defer-panic-and-recover.html

On 11/04/2013 00:16, Chet Murthy wrote:
> 
> People have previously asked about try...finally support in Ocaml, and
> it's been observed (correctly) that you can write a little combinator
> to give you this support, e.g.
> 
> let finally f arg finf =
>   let rv = try Inl(f arg) with e ->
>     Inr e
>   in (try finf arg rv with e -> ());
> 	match rv with
> 		Inl v -> v
> 	  | Inr e -> raise e
> 
> The problem is, you discard stack-traceback when you rethrow the
> exception.  One can program around this explicitly by capturing the
> backtrace string and appending it to the rethrown exception, but it's
> cumbersome and won't work for exceptions like Not_found that are
> already defined without a mutable string slot.
> 
> It sure would be nice of ocaml had try...finally that preserved the
> traceback information properly .... though maybe it isn't possible.
> Certainly in the case where the finally block doesn't raise any
> exceptions itself (even those that are caught silently), it seems like
> it ought to be possible.
> 
> In an unrelated but similar sense, when programming with threads in
> ocaml, it's easy (easy!) to deadlock your program.  Now, I've been
> writing Java programs for years, and so am aware of how careful one
> must be, and I'm writing my code using a single mutex protecting the
> critical section.  But I forgot and didn't mutex-protect one method --
> what merely printed out the contents of a shared daa-structure, and
> when that printout coincided with a thread actually mutating the
> data-structure, I got a deadlock.  Not hard to track down, and I
> chided myself for being lax.
> 
> But the thing is, in Java (blecch!) I would have been able to use the
> "javacore" facility to get a full-thread stack-traceback, and could
> have used that to get a good idea of where my deadlock was.
> 
> I'm not saying that this is something ocaml should have, but I figured
> I'd ask: are others (who use threads in ocaml) wishing for something
> like this?
> 
> --chet--
> 
> 
> 


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [Caml-list] try...finally , threads, stack-tracebacks .... in ocaml
  2013-04-10 22:16 [Caml-list] try...finally , threads, stack-tracebacks .... in ocaml Chet Murthy
  2013-04-10 22:28 ` simon cruanes
@ 2013-04-10 23:35 ` Yaron Minsky
  2013-04-10 23:37   ` Yaron Minsky
  2013-04-11  6:25 ` Jacques-Henri Jourdan
  2 siblings, 1 reply; 14+ messages in thread
From: Yaron Minsky @ 2013-04-10 23:35 UTC (permalink / raw)
  To: Chet Murthy; +Cc: Caml List

Chet, are you sure that one looses the stack trace in this case?  My
example using Core seems to preserve it.  Here's the code:

    open Core.Std

    let a () = let _ = "a" in raise Not_found
    let b () = let _ = "b" in a ()

    let c () =
      let _ = "c" in
      protect ~f:b
        ~finally:(fun () -> ())

    let d () = let _ = "d" in c ()
    let () = d ()

And here's the native code stack-trace:

    $ ./z.native
    Fatal error: exception Not_found
    Raised at file "z.ml", line 3, characters 32-41
    Called from file "lib/exn.ml", line 63, characters 8-11
    Re-raised at file "lib/exn.ml", line 66, characters 12-15
    Called from file "z.ml", line 11, characters 26-30

Here's the code for protect, which is a little different than your
finally, but not by a lot.  Maybe the biggest difference is that we
have a special exception (Finally) which we use when the finally
clause throws an exception from an exception handler, so we can
deliver both the exception tha triggered the [finally] and the
exception thrown by the [finally].

This is from the Exn module in Core.

    let protectx ~f x ~(finally : _ -> unit) =
      let res =
        try f x
        with exn ->
          (try finally x with final_exn -> raise (Finally (exn, final_exn)));
          raise exn
      in
      finally x;
      res
    ;;

    let protect ~f ~finally = protectx ~f () ~finally


On Wed, Apr 10, 2013 at 6:16 PM, Chet Murthy <murthy.chet@gmail.com> wrote:
>
> People have previously asked about try...finally support in Ocaml, and
> it's been observed (correctly) that you can write a little combinator
> to give you this support, e.g.
>
> let finally f arg finf =
>   let rv = try Inl(f arg) with e ->
>     Inr e
>   in (try finf arg rv with e -> ());
>         match rv with
>                 Inl v -> v
>           | Inr e -> raise e
>
> The problem is, you discard stack-traceback when you rethrow the
> exception.  One can program around this explicitly by capturing the
> backtrace string and appending it to the rethrown exception, but it's
> cumbersome and won't work for exceptions like Not_found that are
> already defined without a mutable string slot.
>
> It sure would be nice of ocaml had try...finally that preserved the
> traceback information properly .... though maybe it isn't possible.
> Certainly in the case where the finally block doesn't raise any
> exceptions itself (even those that are caught silently), it seems like
> it ought to be possible.
>
> In an unrelated but similar sense, when programming with threads in
> ocaml, it's easy (easy!) to deadlock your program.  Now, I've been
> writing Java programs for years, and so am aware of how careful one
> must be, and I'm writing my code using a single mutex protecting the
> critical section.  But I forgot and didn't mutex-protect one method --
> what merely printed out the contents of a shared daa-structure, and
> when that printout coincided with a thread actually mutating the
> data-structure, I got a deadlock.  Not hard to track down, and I
> chided myself for being lax.
>
> But the thing is, in Java (blecch!) I would have been able to use the
> "javacore" facility to get a full-thread stack-traceback, and could
> have used that to get a good idea of where my deadlock was.
>
> I'm not saying that this is something ocaml should have, but I figured
> I'd ask: are others (who use threads in ocaml) wishing for something
> like this?
>
> --chet--
>
>
>
> --
> Caml-list mailing list.  Subscription management and archives:
> https://sympa.inria.fr/sympa/arc/caml-list
> Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
> Bug reports: http://caml.inria.fr/bin/caml-bugs

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [Caml-list] try...finally , threads, stack-tracebacks .... in ocaml
  2013-04-10 23:35 ` Yaron Minsky
@ 2013-04-10 23:37   ` Yaron Minsky
  2013-04-11  6:36     ` Malcolm Matalka
  0 siblings, 1 reply; 14+ messages in thread
From: Yaron Minsky @ 2013-04-10 23:37 UTC (permalink / raw)
  To: Chet Murthy; +Cc: Caml List

Oh, and as for the thread part of your point, I would strongly
recommend using a monadic concurrency library like Async or Lwt rather
than coding with system threads in OCaml.  It does kill your
stack-traces (stack-traces and monadic libraries don't work so well
together), but it's totally worth the trade-off.  Certainly your
deadlock and race-condition problems get a hell of a lot better.

y

On Wed, Apr 10, 2013 at 7:35 PM, Yaron Minsky <yminsky@janestreet.com> wrote:
> Chet, are you sure that one looses the stack trace in this case?  My
> example using Core seems to preserve it.  Here's the code:
>
>     open Core.Std
>
>     let a () = let _ = "a" in raise Not_found
>     let b () = let _ = "b" in a ()
>
>     let c () =
>       let _ = "c" in
>       protect ~f:b
>         ~finally:(fun () -> ())
>
>     let d () = let _ = "d" in c ()
>     let () = d ()
>
> And here's the native code stack-trace:
>
>     $ ./z.native
>     Fatal error: exception Not_found
>     Raised at file "z.ml", line 3, characters 32-41
>     Called from file "lib/exn.ml", line 63, characters 8-11
>     Re-raised at file "lib/exn.ml", line 66, characters 12-15
>     Called from file "z.ml", line 11, characters 26-30
>
> Here's the code for protect, which is a little different than your
> finally, but not by a lot.  Maybe the biggest difference is that we
> have a special exception (Finally) which we use when the finally
> clause throws an exception from an exception handler, so we can
> deliver both the exception tha triggered the [finally] and the
> exception thrown by the [finally].
>
> This is from the Exn module in Core.
>
>     let protectx ~f x ~(finally : _ -> unit) =
>       let res =
>         try f x
>         with exn ->
>           (try finally x with final_exn -> raise (Finally (exn, final_exn)));
>           raise exn
>       in
>       finally x;
>       res
>     ;;
>
>     let protect ~f ~finally = protectx ~f () ~finally
>
>
> On Wed, Apr 10, 2013 at 6:16 PM, Chet Murthy <murthy.chet@gmail.com> wrote:
>>
>> People have previously asked about try...finally support in Ocaml, and
>> it's been observed (correctly) that you can write a little combinator
>> to give you this support, e.g.
>>
>> let finally f arg finf =
>>   let rv = try Inl(f arg) with e ->
>>     Inr e
>>   in (try finf arg rv with e -> ());
>>         match rv with
>>                 Inl v -> v
>>           | Inr e -> raise e
>>
>> The problem is, you discard stack-traceback when you rethrow the
>> exception.  One can program around this explicitly by capturing the
>> backtrace string and appending it to the rethrown exception, but it's
>> cumbersome and won't work for exceptions like Not_found that are
>> already defined without a mutable string slot.
>>
>> It sure would be nice of ocaml had try...finally that preserved the
>> traceback information properly .... though maybe it isn't possible.
>> Certainly in the case where the finally block doesn't raise any
>> exceptions itself (even those that are caught silently), it seems like
>> it ought to be possible.
>>
>> In an unrelated but similar sense, when programming with threads in
>> ocaml, it's easy (easy!) to deadlock your program.  Now, I've been
>> writing Java programs for years, and so am aware of how careful one
>> must be, and I'm writing my code using a single mutex protecting the
>> critical section.  But I forgot and didn't mutex-protect one method --
>> what merely printed out the contents of a shared daa-structure, and
>> when that printout coincided with a thread actually mutating the
>> data-structure, I got a deadlock.  Not hard to track down, and I
>> chided myself for being lax.
>>
>> But the thing is, in Java (blecch!) I would have been able to use the
>> "javacore" facility to get a full-thread stack-traceback, and could
>> have used that to get a good idea of where my deadlock was.
>>
>> I'm not saying that this is something ocaml should have, but I figured
>> I'd ask: are others (who use threads in ocaml) wishing for something
>> like this?
>>
>> --chet--
>>
>>
>>
>> --
>> Caml-list mailing list.  Subscription management and archives:
>> https://sympa.inria.fr/sympa/arc/caml-list
>> Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
>> Bug reports: http://caml.inria.fr/bin/caml-bugs

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [Caml-list] try...finally , threads, stack-tracebacks .... in ocaml
  2013-04-10 22:28 ` simon cruanes
@ 2013-04-11  0:19   ` Francois Berenger
  0 siblings, 0 replies; 14+ messages in thread
From: Francois Berenger @ 2013-04-11  0:19 UTC (permalink / raw)
  To: caml-list

On 04/11/2013 07:28 AM, simon cruanes wrote:
> An interesting solution for the safe resource acquisition/release, I
> believe, is the Go statement "defer" [1]. In OCaml, you would write
> something like:
>
> let my_fun () =
>    Mutex.lock some_lock;
>    defer (fun () -> Mutex.unlock some_lock);
>    (* critical section to the end of the block *)
>    ....
>    let final_result = 42 in
>    final_result   (* returns, but runs defer-ed statements first *)
>
> In case an exception is thrown before the function returns, defer-ed
> statements would still be executed, before the exception is raised again
> (with the full stacktrace). Defer-ed statements are executed in the
> reverse order of their definitions. It also works for resources like
> files, sockets, etc.

There is at_exit from Pervasives that looks like a defer, but only
at the program level unfortunately.

I think I read that at Citrix thay garbage-collect everything:
open files, acquired locks, etc.
I have no idea of how they manage to do this, however.

Regards,
F.

> Simon
>
> [1] http://blog.golang.org/2010/08/defer-panic-and-recover.html
>
> On 11/04/2013 00:16, Chet Murthy wrote:
>>
>> People have previously asked about try...finally support in Ocaml, and
>> it's been observed (correctly) that you can write a little combinator
>> to give you this support, e.g.
>>
>> let finally f arg finf =
>>    let rv = try Inl(f arg) with e ->
>>      Inr e
>>    in (try finf arg rv with e -> ());
>> 	match rv with
>> 		Inl v -> v
>> 	  | Inr e -> raise e
>>
>> The problem is, you discard stack-traceback when you rethrow the
>> exception.  One can program around this explicitly by capturing the
>> backtrace string and appending it to the rethrown exception, but it's
>> cumbersome and won't work for exceptions like Not_found that are
>> already defined without a mutable string slot.
>>
>> It sure would be nice of ocaml had try...finally that preserved the
>> traceback information properly .... though maybe it isn't possible.
>> Certainly in the case where the finally block doesn't raise any
>> exceptions itself (even those that are caught silently), it seems like
>> it ought to be possible.
>>
>> In an unrelated but similar sense, when programming with threads in
>> ocaml, it's easy (easy!) to deadlock your program.  Now, I've been
>> writing Java programs for years, and so am aware of how careful one
>> must be, and I'm writing my code using a single mutex protecting the
>> critical section.  But I forgot and didn't mutex-protect one method --
>> what merely printed out the contents of a shared daa-structure, and
>> when that printout coincided with a thread actually mutating the
>> data-structure, I got a deadlock.  Not hard to track down, and I
>> chided myself for being lax.
>>
>> But the thing is, in Java (blecch!) I would have been able to use the
>> "javacore" facility to get a full-thread stack-traceback, and could
>> have used that to get a good idea of where my deadlock was.
>>
>> I'm not saying that this is something ocaml should have, but I figured
>> I'd ask: are others (who use threads in ocaml) wishing for something
>> like this?
>>
>> --chet--
>>
>>
>>
>
>


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [Caml-list] try...finally , threads, stack-tracebacks .... in ocaml
  2013-04-10 22:16 [Caml-list] try...finally , threads, stack-tracebacks .... in ocaml Chet Murthy
  2013-04-10 22:28 ` simon cruanes
  2013-04-10 23:35 ` Yaron Minsky
@ 2013-04-11  6:25 ` Jacques-Henri Jourdan
  2 siblings, 0 replies; 14+ messages in thread
From: Jacques-Henri Jourdan @ 2013-04-11  6:25 UTC (permalink / raw)
  To: caml-list

[-- Attachment #1: Type: text/plain, Size: 2482 bytes --]

Hi,

I recently published a blog post proposing a solution to the backtrace
problem of Ocaml. It includes a Camlp4 filter and a small Ocaml library
to handle exception backtraces. The performance drawback is negligible
when backtraces are not activated, and reasonable when they are.

You can read about it here :

http://gallium.inria.fr/blog/a-library-to-record-ocaml-backtraces/

-- 
JH Jourdan

Le 11/04/2013 00:16, Chet Murthy a écrit :
> 
> People have previously asked about try...finally support in Ocaml, and
> it's been observed (correctly) that you can write a little combinator
> to give you this support, e.g.
> 
> let finally f arg finf =
>   let rv = try Inl(f arg) with e ->
>     Inr e
>   in (try finf arg rv with e -> ());
> 	match rv with
> 		Inl v -> v
> 	  | Inr e -> raise e
> 
> The problem is, you discard stack-traceback when you rethrow the
> exception.  One can program around this explicitly by capturing the
> backtrace string and appending it to the rethrown exception, but it's
> cumbersome and won't work for exceptions like Not_found that are
> already defined without a mutable string slot.
> 
> It sure would be nice of ocaml had try...finally that preserved the
> traceback information properly .... though maybe it isn't possible.
> Certainly in the case where the finally block doesn't raise any
> exceptions itself (even those that are caught silently), it seems like
> it ought to be possible.
> 
> In an unrelated but similar sense, when programming with threads in
> ocaml, it's easy (easy!) to deadlock your program.  Now, I've been
> writing Java programs for years, and so am aware of how careful one
> must be, and I'm writing my code using a single mutex protecting the
> critical section.  But I forgot and didn't mutex-protect one method --
> what merely printed out the contents of a shared daa-structure, and
> when that printout coincided with a thread actually mutating the
> data-structure, I got a deadlock.  Not hard to track down, and I
> chided myself for being lax.
> 
> But the thing is, in Java (blecch!) I would have been able to use the
> "javacore" facility to get a full-thread stack-traceback, and could
> have used that to get a good idea of where my deadlock was.
> 
> I'm not saying that this is something ocaml should have, but I figured
> I'd ask: are others (who use threads in ocaml) wishing for something
> like this?
> 
> --chet--
> 
> 
> 



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 555 bytes --]

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [Caml-list] try...finally , threads, stack-tracebacks .... in ocaml
  2013-04-10 23:37   ` Yaron Minsky
@ 2013-04-11  6:36     ` Malcolm Matalka
  2013-04-11  6:42       ` Chet Murthy
  0 siblings, 1 reply; 14+ messages in thread
From: Malcolm Matalka @ 2013-04-11  6:36 UTC (permalink / raw)
  To: Yaron Minsky; +Cc: Chet Murthy, Caml List

On top of this, I have also had a lot of success using the Result type
(and associated Monad) instead of Exceptions in Ocaml.  You have to have
a certain level of discipline to enjoy doing it completely but I have
never had a stack-trace issue doing it because you already know where
you have to handle every failure case.

/M

Yaron Minsky <yminsky@janestreet.com> writes:

> Oh, and as for the thread part of your point, I would strongly
> recommend using a monadic concurrency library like Async or Lwt rather
> than coding with system threads in OCaml.  It does kill your
> stack-traces (stack-traces and monadic libraries don't work so well
> together), but it's totally worth the trade-off.  Certainly your
> deadlock and race-condition problems get a hell of a lot better.
>
> y
>
> On Wed, Apr 10, 2013 at 7:35 PM, Yaron Minsky <yminsky@janestreet.com> wrote:
>> Chet, are you sure that one looses the stack trace in this case?  My
>> example using Core seems to preserve it.  Here's the code:
>>
>>     open Core.Std
>>
>>     let a () = let _ = "a" in raise Not_found
>>     let b () = let _ = "b" in a ()
>>
>>     let c () =
>>       let _ = "c" in
>>       protect ~f:b
>>         ~finally:(fun () -> ())
>>
>>     let d () = let _ = "d" in c ()
>>     let () = d ()
>>
>> And here's the native code stack-trace:
>>
>>     $ ./z.native
>>     Fatal error: exception Not_found
>>     Raised at file "z.ml", line 3, characters 32-41
>>     Called from file "lib/exn.ml", line 63, characters 8-11
>>     Re-raised at file "lib/exn.ml", line 66, characters 12-15
>>     Called from file "z.ml", line 11, characters 26-30
>>
>> Here's the code for protect, which is a little different than your
>> finally, but not by a lot.  Maybe the biggest difference is that we
>> have a special exception (Finally) which we use when the finally
>> clause throws an exception from an exception handler, so we can
>> deliver both the exception tha triggered the [finally] and the
>> exception thrown by the [finally].
>>
>> This is from the Exn module in Core.
>>
>>     let protectx ~f x ~(finally : _ -> unit) =
>>       let res =
>>         try f x
>>         with exn ->
>>           (try finally x with final_exn -> raise (Finally (exn, final_exn)));
>>           raise exn
>>       in
>>       finally x;
>>       res
>>     ;;
>>
>>     let protect ~f ~finally = protectx ~f () ~finally
>>
>>
>> On Wed, Apr 10, 2013 at 6:16 PM, Chet Murthy <murthy.chet@gmail.com> wrote:
>>>
>>> People have previously asked about try...finally support in Ocaml, and
>>> it's been observed (correctly) that you can write a little combinator
>>> to give you this support, e.g.
>>>
>>> let finally f arg finf =
>>>   let rv = try Inl(f arg) with e ->
>>>     Inr e
>>>   in (try finf arg rv with e -> ());
>>>         match rv with
>>>                 Inl v -> v
>>>           | Inr e -> raise e
>>>
>>> The problem is, you discard stack-traceback when you rethrow the
>>> exception.  One can program around this explicitly by capturing the
>>> backtrace string and appending it to the rethrown exception, but it's
>>> cumbersome and won't work for exceptions like Not_found that are
>>> already defined without a mutable string slot.
>>>
>>> It sure would be nice of ocaml had try...finally that preserved the
>>> traceback information properly .... though maybe it isn't possible.
>>> Certainly in the case where the finally block doesn't raise any
>>> exceptions itself (even those that are caught silently), it seems like
>>> it ought to be possible.
>>>
>>> In an unrelated but similar sense, when programming with threads in
>>> ocaml, it's easy (easy!) to deadlock your program.  Now, I've been
>>> writing Java programs for years, and so am aware of how careful one
>>> must be, and I'm writing my code using a single mutex protecting the
>>> critical section.  But I forgot and didn't mutex-protect one method --
>>> what merely printed out the contents of a shared daa-structure, and
>>> when that printout coincided with a thread actually mutating the
>>> data-structure, I got a deadlock.  Not hard to track down, and I
>>> chided myself for being lax.
>>>
>>> But the thing is, in Java (blecch!) I would have been able to use the
>>> "javacore" facility to get a full-thread stack-traceback, and could
>>> have used that to get a good idea of where my deadlock was.
>>>
>>> I'm not saying that this is something ocaml should have, but I figured
>>> I'd ask: are others (who use threads in ocaml) wishing for something
>>> like this?
>>>
>>> --chet--
>>>
>>>
>>>
>>> --
>>> Caml-list mailing list.  Subscription management and archives:
>>> https://sympa.inria.fr/sympa/arc/caml-list
>>> Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
>>> Bug reports: http://caml.inria.fr/bin/caml-bugs

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [Caml-list] try...finally , threads, stack-tracebacks .... in ocaml
  2013-04-11  6:36     ` Malcolm Matalka
@ 2013-04-11  6:42       ` Chet Murthy
  2013-04-11  7:11         ` Francois Berenger
                           ` (2 more replies)
  0 siblings, 3 replies; 14+ messages in thread
From: Chet Murthy @ 2013-04-11  6:42 UTC (permalink / raw)
  To: Caml List


I agree that a monadic style would be nice.  Of course, you'd lose
even -more- of your stack (as it disappears into the
continuation-chain).  In this case, I'm working with code (Thrift)
that relies on threads, and while I could fix it, right now is not the
time.  So threads are an externally-imposed requirement.

Also, I notice that nobody's mentioned any sort of solution to "my
threaded program deadlocked; I'm pretty sure I screwed up my locking
-- how can I find out where the threads are stuck?"  I'm not saying
there -is- a solution: quite to the contrary.

Multi-threaded programming (yes, even with a GIL) is here to say in
Ocaml, and I think that the ability to get even a -rudimentary-
"javacore"-like dump, would be useful.  Even in just bytecode mode.

It's been -forever- since I walked around in the ZAM, but Iguess
sometime I'll have to take a look.  In the meantime, does anybody out
there have a -guess- as to the difficulty of getting such a dump out
of the ZAM?

--chet--

On Thursday, April 11, 2013 02:36:06 AM Malcolm Matalka wrote:
> On top of this, I have also had a lot of success using the Result type
> (and associated Monad) instead of Exceptions in Ocaml.  You have to have
> a certain level of discipline to enjoy doing it completely but I have
> never had a stack-trace issue doing it because you already know where
> you have to handle every failure case.
> 
> /M
> 
> Yaron Minsky <yminsky@janestreet.com> writes:
> > Oh, and as for the thread part of your point, I would strongly
> > recommend using a monadic concurrency library like Async or Lwt rather
> > than coding with system threads in OCaml.  It does kill your
> > stack-traces (stack-traces and monadic libraries don't work so well
> > together), but it's totally worth the trade-off.  Certainly your
> > deadlock and race-condition problems get a hell of a lot better.
> > 
> > y
> > 
> > On Wed, Apr 10, 2013 at 7:35 PM, Yaron Minsky <yminsky@janestreet.com> 
wrote:
> >> Chet, are you sure that one looses the stack trace in this case?  My
> >> 
> >> example using Core seems to preserve it.  Here's the code:
> >>     open Core.Std
> >>     
> >>     let a () = let _ = "a" in raise Not_found
> >>     let b () = let _ = "b" in a ()
> >>     
> >>     let c () =
> >>     
> >>       let _ = "c" in
> >>       protect ~f:b
> >>       
> >>         ~finally:(fun () -> ())
> >>     
> >>     let d () = let _ = "d" in c ()
> >>     let () = d ()
> >> 
> >> And here's the native code stack-trace:
> >>     $ ./z.native
> >>     Fatal error: exception Not_found
> >>     Raised at file "z.ml", line 3, characters 32-41
> >>     Called from file "lib/exn.ml", line 63, characters 8-11
> >>     Re-raised at file "lib/exn.ml", line 66, characters 12-15
> >>     Called from file "z.ml", line 11, characters 26-30
> >> 
> >> Here's the code for protect, which is a little different than your
> >> finally, but not by a lot.  Maybe the biggest difference is that we
> >> have a special exception (Finally) which we use when the finally
> >> clause throws an exception from an exception handler, so we can
> >> deliver both the exception tha triggered the [finally] and the
> >> exception thrown by the [finally].
> >> 
> >> This is from the Exn module in Core.
> >> 
> >>     let protectx ~f x ~(finally : _ -> unit) =
> >>     
> >>       let res =
> >>       
> >>         try f x
> >>         with exn ->
> >>         
> >>           (try finally x with final_exn -> raise (Finally (exn,
> >>           final_exn)));
> >>           raise exn
> >>       
> >>       in
> >>       finally x;
> >>       res
> >>     
> >>     ;;
> >>     
> >>     let protect ~f ~finally = protectx ~f () ~finally
> >> 
> >> On Wed, Apr 10, 2013 at 6:16 PM, Chet Murthy <murthy.chet@gmail.com> 
wrote:
> >>> People have previously asked about try...finally support in Ocaml, and
> >>> it's been observed (correctly) that you can write a little combinator
> >>> to give you this support, e.g.
> >>> 
> >>> let finally f arg finf =
> >>> 
> >>>   let rv = try Inl(f arg) with e ->
> >>>   
> >>>     Inr e
> >>>   
> >>>   in (try finf arg rv with e -> ());
> >>>   
> >>>         match rv with
> >>>         
> >>>                 Inl v -> v
> >>>           | 
> >>>           | Inr e -> raise e
> >>> 
> >>> The problem is, you discard stack-traceback when you rethrow the
> >>> exception.  One can program around this explicitly by capturing the
> >>> backtrace string and appending it to the rethrown exception, but it's
> >>> cumbersome and won't work for exceptions like Not_found that are
> >>> already defined without a mutable string slot.
> >>> 
> >>> It sure would be nice of ocaml had try...finally that preserved the
> >>> traceback information properly .... though maybe it isn't possible.
> >>> Certainly in the case where the finally block doesn't raise any
> >>> exceptions itself (even those that are caught silently), it seems like
> >>> it ought to be possible.
> >>> 
> >>> In an unrelated but similar sense, when programming with threads in
> >>> ocaml, it's easy (easy!) to deadlock your program.  Now, I've been
> >>> writing Java programs for years, and so am aware of how careful one
> >>> must be, and I'm writing my code using a single mutex protecting the
> >>> critical section.  But I forgot and didn't mutex-protect one method --
> >>> what merely printed out the contents of a shared daa-structure, and
> >>> when that printout coincided with a thread actually mutating the
> >>> data-structure, I got a deadlock.  Not hard to track down, and I
> >>> chided myself for being lax.
> >>> 
> >>> But the thing is, in Java (blecch!) I would have been able to use the
> >>> "javacore" facility to get a full-thread stack-traceback, and could
> >>> have used that to get a good idea of where my deadlock was.
> >>> 
> >>> I'm not saying that this is something ocaml should have, but I figured
> >>> I'd ask: are others (who use threads in ocaml) wishing for something
> >>> like this?
> >>> 
> >>> --chet--
> >>> 
> >>> 
> >>> 
> >>> --
> >>> Caml-list mailing list.  Subscription management and archives:
> >>> https://sympa.inria.fr/sympa/arc/caml-list
> >>> Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
> >>> Bug reports: http://caml.inria.fr/bin/caml-bugs

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [Caml-list] try...finally , threads, stack-tracebacks .... in ocaml
  2013-04-11  6:42       ` Chet Murthy
@ 2013-04-11  7:11         ` Francois Berenger
  2013-04-11  7:17           ` Chet Murthy
  2013-04-11  8:48         ` Malcolm Matalka
  2013-04-11 11:13         ` Thomas Gazagnaire
  2 siblings, 1 reply; 14+ messages in thread
From: Francois Berenger @ 2013-04-11  7:11 UTC (permalink / raw)
  To: caml-list

On 04/11/2013 03:42 PM, Chet Murthy wrote:
>
> I agree that a monadic style would be nice.  Of course, you'd lose
> even -more- of your stack (as it disappears into the
> continuation-chain).  In this case, I'm working with code (Thrift)
> that relies on threads, and while I could fix it, right now is not the
> time.  So threads are an externally-imposed requirement.
>
> Also, I notice that nobody's mentioned any sort of solution to "my
> threaded program deadlocked; I'm pretty sure I screwed up my locking
> -- how can I find out where the threads are stuck?"  I'm not saying
> there -is- a solution: quite to the contrary.

Isn't there a way to "trace" locking and unlocking of locks?

So that you can do a post-mortem analysis of what went wrong.

> Multi-threaded programming (yes, even with a GIL) is here to say in
> Ocaml, and I think that the ability to get even a -rudimentary-
> "javacore"-like dump, would be useful.  Even in just bytecode mode.
>
> It's been -forever- since I walked around in the ZAM, but Iguess
> sometime I'll have to take a look.  In the meantime, does anybody out
> there have a -guess- as to the difficulty of getting such a dump out
> of the ZAM?

What is the ZAM?

Regards,
F.

PS: I hate threads, but I _love_ processes ;)

> --chet--
>
> On Thursday, April 11, 2013 02:36:06 AM Malcolm Matalka wrote:
>> On top of this, I have also had a lot of success using the Result type
>> (and associated Monad) instead of Exceptions in Ocaml.  You have to have
>> a certain level of discipline to enjoy doing it completely but I have
>> never had a stack-trace issue doing it because you already know where
>> you have to handle every failure case.
>>
>> /M
>>
>> Yaron Minsky <yminsky@janestreet.com> writes:
>>> Oh, and as for the thread part of your point, I would strongly
>>> recommend using a monadic concurrency library like Async or Lwt rather
>>> than coding with system threads in OCaml.  It does kill your
>>> stack-traces (stack-traces and monadic libraries don't work so well
>>> together), but it's totally worth the trade-off.  Certainly your
>>> deadlock and race-condition problems get a hell of a lot better.
>>>
>>> y
>>>
>>> On Wed, Apr 10, 2013 at 7:35 PM, Yaron Minsky <yminsky@janestreet.com>
> wrote:
>>>> Chet, are you sure that one looses the stack trace in this case?  My
>>>>
>>>> example using Core seems to preserve it.  Here's the code:
>>>>      open Core.Std
>>>>
>>>>      let a () = let _ = "a" in raise Not_found
>>>>      let b () = let _ = "b" in a ()
>>>>
>>>>      let c () =
>>>>
>>>>        let _ = "c" in
>>>>        protect ~f:b
>>>>
>>>>          ~finally:(fun () -> ())
>>>>
>>>>      let d () = let _ = "d" in c ()
>>>>      let () = d ()
>>>>
>>>> And here's the native code stack-trace:
>>>>      $ ./z.native
>>>>      Fatal error: exception Not_found
>>>>      Raised at file "z.ml", line 3, characters 32-41
>>>>      Called from file "lib/exn.ml", line 63, characters 8-11
>>>>      Re-raised at file "lib/exn.ml", line 66, characters 12-15
>>>>      Called from file "z.ml", line 11, characters 26-30
>>>>
>>>> Here's the code for protect, which is a little different than your
>>>> finally, but not by a lot.  Maybe the biggest difference is that we
>>>> have a special exception (Finally) which we use when the finally
>>>> clause throws an exception from an exception handler, so we can
>>>> deliver both the exception tha triggered the [finally] and the
>>>> exception thrown by the [finally].
>>>>
>>>> This is from the Exn module in Core.
>>>>
>>>>      let protectx ~f x ~(finally : _ -> unit) =
>>>>
>>>>        let res =
>>>>
>>>>          try f x
>>>>          with exn ->
>>>>
>>>>            (try finally x with final_exn -> raise (Finally (exn,
>>>>            final_exn)));
>>>>            raise exn
>>>>
>>>>        in
>>>>        finally x;
>>>>        res
>>>>
>>>>      ;;
>>>>
>>>>      let protect ~f ~finally = protectx ~f () ~finally
>>>>
>>>> On Wed, Apr 10, 2013 at 6:16 PM, Chet Murthy <murthy.chet@gmail.com>
> wrote:
>>>>> People have previously asked about try...finally support in Ocaml, and
>>>>> it's been observed (correctly) that you can write a little combinator
>>>>> to give you this support, e.g.
>>>>>
>>>>> let finally f arg finf =
>>>>>
>>>>>    let rv = try Inl(f arg) with e ->
>>>>>
>>>>>      Inr e
>>>>>
>>>>>    in (try finf arg rv with e -> ());
>>>>>
>>>>>          match rv with
>>>>>
>>>>>                  Inl v -> v
>>>>>            |
>>>>>            | Inr e -> raise e
>>>>>
>>>>> The problem is, you discard stack-traceback when you rethrow the
>>>>> exception.  One can program around this explicitly by capturing the
>>>>> backtrace string and appending it to the rethrown exception, but it's
>>>>> cumbersome and won't work for exceptions like Not_found that are
>>>>> already defined without a mutable string slot.
>>>>>
>>>>> It sure would be nice of ocaml had try...finally that preserved the
>>>>> traceback information properly .... though maybe it isn't possible.
>>>>> Certainly in the case where the finally block doesn't raise any
>>>>> exceptions itself (even those that are caught silently), it seems like
>>>>> it ought to be possible.
>>>>>
>>>>> In an unrelated but similar sense, when programming with threads in
>>>>> ocaml, it's easy (easy!) to deadlock your program.  Now, I've been
>>>>> writing Java programs for years, and so am aware of how careful one
>>>>> must be, and I'm writing my code using a single mutex protecting the
>>>>> critical section.  But I forgot and didn't mutex-protect one method --
>>>>> what merely printed out the contents of a shared daa-structure, and
>>>>> when that printout coincided with a thread actually mutating the
>>>>> data-structure, I got a deadlock.  Not hard to track down, and I
>>>>> chided myself for being lax.
>>>>>
>>>>> But the thing is, in Java (blecch!) I would have been able to use the
>>>>> "javacore" facility to get a full-thread stack-traceback, and could
>>>>> have used that to get a good idea of where my deadlock was.
>>>>>
>>>>> I'm not saying that this is something ocaml should have, but I figured
>>>>> I'd ask: are others (who use threads in ocaml) wishing for something
>>>>> like this?
>>>>>
>>>>> --chet--
>>>>>
>>>>>
>>>>>
>>>>> --
>>>>> Caml-list mailing list.  Subscription management and archives:
>>>>> https://sympa.inria.fr/sympa/arc/caml-list
>>>>> Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
>>>>> Bug reports: http://caml.inria.fr/bin/caml-bugs
>


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [Caml-list] try...finally , threads, stack-tracebacks .... in ocaml
  2013-04-11  7:11         ` Francois Berenger
@ 2013-04-11  7:17           ` Chet Murthy
  2013-04-11  8:04             ` Roberto Di Cosmo
  0 siblings, 1 reply; 14+ messages in thread
From: Chet Murthy @ 2013-04-11  7:17 UTC (permalink / raw)
  To: caml-list; +Cc: Francois Berenger


> Isn't there a way to "trace" locking and unlocking of locks?
> 
> So that you can do a post-mortem analysis of what went wrong.

Sure.  But you'd need more locks to manage that, yes?  And
furthermore, the problem (in the case I was debugging, and many times
in my times debugging java apps) is that somebody -didn't- put locking
in plcae (e.g., java.util.NumberFormat isn't thread-safe, and yet
people will create static instances and use 'em from multiple threads,
yielding "interesting" results).

But really that's immaterial.  You can't use tracing to find
timing-related issues, b/c the trace changes the timing.

> What is the ZAM?

Sorry, the original name for the Ocaml VM was the Zinc Abstract
Machine (from Xavier's original paper).

--chet--


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [Caml-list] try...finally , threads, stack-tracebacks .... in ocaml
  2013-04-11  7:17           ` Chet Murthy
@ 2013-04-11  8:04             ` Roberto Di Cosmo
  0 siblings, 0 replies; 14+ messages in thread
From: Roberto Di Cosmo @ 2013-04-11  8:04 UTC (permalink / raw)
  To: Chet Murthy; +Cc: caml-list

Hi Chet,

On Thu, Apr 11, 2013 at 12:17:51AM -0700, Chet Murthy wrote:
> 
> But really that's immaterial.  You can't use tracing to find
> timing-related issues, b/c the trace changes the timing.
> 

Thanks for this comment : it just recalled some fond memories of my
friends in the parallel computing group in Pisa more than 20 years
ago, sharing their frustration in trying to trace bugs in parallel
Occam code : in a particularly sneaky case, the bug disappeared
as soon as debugging was enabled, and even inserting a
single print function altered the timing enough to make 
it vanish...

Programming parallel/concurrent systems can be *sooo* much fun :-)

-- 
Roberto
 
------------------------------------------------------------------
Professeur               En delegation a l'INRIA
PPS                      E-mail: roberto@dicosmo.org
Universite Paris Diderot WWW  : http://www.dicosmo.org
Case 7014                Tel  : ++33-(0)1-57 27 92 20
5, Rue Thomas Mann       
F-75205 Paris Cedex 13   Identica: http://identi.ca/rdicosmo
FRANCE.                  Twitter: http://twitter.com/rdicosmo
------------------------------------------------------------------
Attachments:
MIME accepted, Word deprecated
      http://www.gnu.org/philosophy/no-word-attachments.html
------------------------------------------------------------------
Office location:
 
Bureau 320 (3rd floor)
Batiment Sophie Germain
Avenue de France
Metro Bibliotheque Francois Mitterrand, ligne 14/RER C
-----------------------------------------------------------------
GPG fingerprint 2931 20CE 3A5A 5390 98EC 8BFC FCCA C3BE 39CB 12D3                        

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [Caml-list] try...finally , threads, stack-tracebacks .... in ocaml
  2013-04-11  6:42       ` Chet Murthy
  2013-04-11  7:11         ` Francois Berenger
@ 2013-04-11  8:48         ` Malcolm Matalka
  2013-04-11 16:43           ` Chet Murthy
  2013-04-11 11:13         ` Thomas Gazagnaire
  2 siblings, 1 reply; 14+ messages in thread
From: Malcolm Matalka @ 2013-04-11  8:48 UTC (permalink / raw)
  To: Chet Murthy; +Cc: Caml List

Out of curiosity, in what way does Thrift impose threads?  Is it
actually handling socket-layer stuff?

Sorry I can't be of more help, I've successfully managed to avoid using
threads in ocaml except for syscalls.

Chet Murthy <murthy.chet@gmail.com> writes:

> I agree that a monadic style would be nice.  Of course, you'd lose
> even -more- of your stack (as it disappears into the
> continuation-chain).  In this case, I'm working with code (Thrift)
> that relies on threads, and while I could fix it, right now is not the
> time.  So threads are an externally-imposed requirement.
>
> Also, I notice that nobody's mentioned any sort of solution to "my
> threaded program deadlocked; I'm pretty sure I screwed up my locking
> -- how can I find out where the threads are stuck?"  I'm not saying
> there -is- a solution: quite to the contrary.
>
> Multi-threaded programming (yes, even with a GIL) is here to say in
> Ocaml, and I think that the ability to get even a -rudimentary-
> "javacore"-like dump, would be useful.  Even in just bytecode mode.
>
> It's been -forever- since I walked around in the ZAM, but Iguess
> sometime I'll have to take a look.  In the meantime, does anybody out
> there have a -guess- as to the difficulty of getting such a dump out
> of the ZAM?
>
> --chet--
>
> On Thursday, April 11, 2013 02:36:06 AM Malcolm Matalka wrote:
>> On top of this, I have also had a lot of success using the Result type
>> (and associated Monad) instead of Exceptions in Ocaml.  You have to have
>> a certain level of discipline to enjoy doing it completely but I have
>> never had a stack-trace issue doing it because you already know where
>> you have to handle every failure case.
>> 
>> /M
>> 
>> Yaron Minsky <yminsky@janestreet.com> writes:
>> > Oh, and as for the thread part of your point, I would strongly
>> > recommend using a monadic concurrency library like Async or Lwt rather
>> > than coding with system threads in OCaml.  It does kill your
>> > stack-traces (stack-traces and monadic libraries don't work so well
>> > together), but it's totally worth the trade-off.  Certainly your
>> > deadlock and race-condition problems get a hell of a lot better.
>> > 
>> > y
>> > 
>> > On Wed, Apr 10, 2013 at 7:35 PM, Yaron Minsky <yminsky@janestreet.com> 
> wrote:
>> >> Chet, are you sure that one looses the stack trace in this case?  My
>> >> 
>> >> example using Core seems to preserve it.  Here's the code:
>> >>     open Core.Std
>> >>     
>> >>     let a () = let _ = "a" in raise Not_found
>> >>     let b () = let _ = "b" in a ()
>> >>     
>> >>     let c () =
>> >>     
>> >>       let _ = "c" in
>> >>       protect ~f:b
>> >>       
>> >>         ~finally:(fun () -> ())
>> >>     
>> >>     let d () = let _ = "d" in c ()
>> >>     let () = d ()
>> >> 
>> >> And here's the native code stack-trace:
>> >>     $ ./z.native
>> >>     Fatal error: exception Not_found
>> >>     Raised at file "z.ml", line 3, characters 32-41
>> >>     Called from file "lib/exn.ml", line 63, characters 8-11
>> >>     Re-raised at file "lib/exn.ml", line 66, characters 12-15
>> >>     Called from file "z.ml", line 11, characters 26-30
>> >> 
>> >> Here's the code for protect, which is a little different than your
>> >> finally, but not by a lot.  Maybe the biggest difference is that we
>> >> have a special exception (Finally) which we use when the finally
>> >> clause throws an exception from an exception handler, so we can
>> >> deliver both the exception tha triggered the [finally] and the
>> >> exception thrown by the [finally].
>> >> 
>> >> This is from the Exn module in Core.
>> >> 
>> >>     let protectx ~f x ~(finally : _ -> unit) =
>> >>     
>> >>       let res =
>> >>       
>> >>         try f x
>> >>         with exn ->
>> >>         
>> >>           (try finally x with final_exn -> raise (Finally (exn,
>> >>           final_exn)));
>> >>           raise exn
>> >>       
>> >>       in
>> >>       finally x;
>> >>       res
>> >>     
>> >>     ;;
>> >>     
>> >>     let protect ~f ~finally = protectx ~f () ~finally
>> >> 
>> >> On Wed, Apr 10, 2013 at 6:16 PM, Chet Murthy <murthy.chet@gmail.com> 
> wrote:
>> >>> People have previously asked about try...finally support in Ocaml, and
>> >>> it's been observed (correctly) that you can write a little combinator
>> >>> to give you this support, e.g.
>> >>> 
>> >>> let finally f arg finf =
>> >>> 
>> >>>   let rv = try Inl(f arg) with e ->
>> >>>   
>> >>>     Inr e
>> >>>   
>> >>>   in (try finf arg rv with e -> ());
>> >>>   
>> >>>         match rv with
>> >>>         
>> >>>                 Inl v -> v
>> >>>           | 
>> >>>           | Inr e -> raise e
>> >>> 
>> >>> The problem is, you discard stack-traceback when you rethrow the
>> >>> exception.  One can program around this explicitly by capturing the
>> >>> backtrace string and appending it to the rethrown exception, but it's
>> >>> cumbersome and won't work for exceptions like Not_found that are
>> >>> already defined without a mutable string slot.
>> >>> 
>> >>> It sure would be nice of ocaml had try...finally that preserved the
>> >>> traceback information properly .... though maybe it isn't possible.
>> >>> Certainly in the case where the finally block doesn't raise any
>> >>> exceptions itself (even those that are caught silently), it seems like
>> >>> it ought to be possible.
>> >>> 
>> >>> In an unrelated but similar sense, when programming with threads in
>> >>> ocaml, it's easy (easy!) to deadlock your program.  Now, I've been
>> >>> writing Java programs for years, and so am aware of how careful one
>> >>> must be, and I'm writing my code using a single mutex protecting the
>> >>> critical section.  But I forgot and didn't mutex-protect one method --
>> >>> what merely printed out the contents of a shared daa-structure, and
>> >>> when that printout coincided with a thread actually mutating the
>> >>> data-structure, I got a deadlock.  Not hard to track down, and I
>> >>> chided myself for being lax.
>> >>> 
>> >>> But the thing is, in Java (blecch!) I would have been able to use the
>> >>> "javacore" facility to get a full-thread stack-traceback, and could
>> >>> have used that to get a good idea of where my deadlock was.
>> >>> 
>> >>> I'm not saying that this is something ocaml should have, but I figured
>> >>> I'd ask: are others (who use threads in ocaml) wishing for something
>> >>> like this?
>> >>> 
>> >>> --chet--
>> >>> 
>> >>> 
>> >>> 
>> >>> --
>> >>> Caml-list mailing list.  Subscription management and archives:
>> >>> https://sympa.inria.fr/sympa/arc/caml-list
>> >>> Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
>> >>> Bug reports: http://caml.inria.fr/bin/caml-bugs

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [Caml-list] try...finally , threads, stack-tracebacks .... in ocaml
  2013-04-11  6:42       ` Chet Murthy
  2013-04-11  7:11         ` Francois Berenger
  2013-04-11  8:48         ` Malcolm Matalka
@ 2013-04-11 11:13         ` Thomas Gazagnaire
  2 siblings, 0 replies; 14+ messages in thread
From: Thomas Gazagnaire @ 2013-04-11 11:13 UTC (permalink / raw)
  To: Chet Murthy; +Cc: Caml List

> Also, I notice that nobody's mentioned any sort of solution to "my
> threaded program deadlocked; I'm pretty sure I screwed up my locking
> -- how can I find out where the threads are stuck?"  I'm not saying
> there -is- a solution: quite to the contrary.

You can attach `gdb` to your dead-locked process and run `thread apply all backtrace`. Sometimes it helps (if you have compiled with -g).

--
Thomas

> 
> Multi-threaded programming (yes, even with a GIL) is here to say in
> Ocaml, and I think that the ability to get even a -rudimentary-
> "javacore"-like dump, would be useful.  Even in just bytecode mode.
> 
> It's been -forever- since I walked around in the ZAM, but Iguess
> sometime I'll have to take a look.  In the meantime, does anybody out
> there have a -guess- as to the difficulty of getting such a dump out
> of the ZAM?
> 
> --chet--
> 
> On Thursday, April 11, 2013 02:36:06 AM Malcolm Matalka wrote:
>> On top of this, I have also had a lot of success using the Result type
>> (and associated Monad) instead of Exceptions in Ocaml.  You have to have
>> a certain level of discipline to enjoy doing it completely but I have
>> never had a stack-trace issue doing it because you already know where
>> you have to handle every failure case.
>> 
>> /M
>> 
>> Yaron Minsky <yminsky@janestreet.com> writes:
>>> Oh, and as for the thread part of your point, I would strongly
>>> recommend using a monadic concurrency library like Async or Lwt rather
>>> than coding with system threads in OCaml.  It does kill your
>>> stack-traces (stack-traces and monadic libraries don't work so well
>>> together), but it's totally worth the trade-off.  Certainly your
>>> deadlock and race-condition problems get a hell of a lot better.
>>> 
>>> y
>>> 
>>> On Wed, Apr 10, 2013 at 7:35 PM, Yaron Minsky <yminsky@janestreet.com> 
> wrote:
>>>> Chet, are you sure that one looses the stack trace in this case?  My
>>>> 
>>>> example using Core seems to preserve it.  Here's the code:
>>>>    open Core.Std
>>>> 
>>>>    let a () = let _ = "a" in raise Not_found
>>>>    let b () = let _ = "b" in a ()
>>>> 
>>>>    let c () =
>>>> 
>>>>      let _ = "c" in
>>>>      protect ~f:b
>>>> 
>>>>        ~finally:(fun () -> ())
>>>> 
>>>>    let d () = let _ = "d" in c ()
>>>>    let () = d ()
>>>> 
>>>> And here's the native code stack-trace:
>>>>    $ ./z.native
>>>>    Fatal error: exception Not_found
>>>>    Raised at file "z.ml", line 3, characters 32-41
>>>>    Called from file "lib/exn.ml", line 63, characters 8-11
>>>>    Re-raised at file "lib/exn.ml", line 66, characters 12-15
>>>>    Called from file "z.ml", line 11, characters 26-30
>>>> 
>>>> Here's the code for protect, which is a little different than your
>>>> finally, but not by a lot.  Maybe the biggest difference is that we
>>>> have a special exception (Finally) which we use when the finally
>>>> clause throws an exception from an exception handler, so we can
>>>> deliver both the exception tha triggered the [finally] and the
>>>> exception thrown by the [finally].
>>>> 
>>>> This is from the Exn module in Core.
>>>> 
>>>>    let protectx ~f x ~(finally : _ -> unit) =
>>>> 
>>>>      let res =
>>>> 
>>>>        try f x
>>>>        with exn ->
>>>> 
>>>>          (try finally x with final_exn -> raise (Finally (exn,
>>>>          final_exn)));
>>>>          raise exn
>>>> 
>>>>      in
>>>>      finally x;
>>>>      res
>>>> 
>>>>    ;;
>>>> 
>>>>    let protect ~f ~finally = protectx ~f () ~finally
>>>> 
>>>> On Wed, Apr 10, 2013 at 6:16 PM, Chet Murthy <murthy.chet@gmail.com> 
> wrote:
>>>>> People have previously asked about try...finally support in Ocaml, and
>>>>> it's been observed (correctly) that you can write a little combinator
>>>>> to give you this support, e.g.
>>>>> 
>>>>> let finally f arg finf =
>>>>> 
>>>>>  let rv = try Inl(f arg) with e ->
>>>>> 
>>>>>    Inr e
>>>>> 
>>>>>  in (try finf arg rv with e -> ());
>>>>> 
>>>>>        match rv with
>>>>> 
>>>>>                Inl v -> v
>>>>>          | 
>>>>>          | Inr e -> raise e
>>>>> 
>>>>> The problem is, you discard stack-traceback when you rethrow the
>>>>> exception.  One can program around this explicitly by capturing the
>>>>> backtrace string and appending it to the rethrown exception, but it's
>>>>> cumbersome and won't work for exceptions like Not_found that are
>>>>> already defined without a mutable string slot.
>>>>> 
>>>>> It sure would be nice of ocaml had try...finally that preserved the
>>>>> traceback information properly .... though maybe it isn't possible.
>>>>> Certainly in the case where the finally block doesn't raise any
>>>>> exceptions itself (even those that are caught silently), it seems like
>>>>> it ought to be possible.
>>>>> 
>>>>> In an unrelated but similar sense, when programming with threads in
>>>>> ocaml, it's easy (easy!) to deadlock your program.  Now, I've been
>>>>> writing Java programs for years, and so am aware of how careful one
>>>>> must be, and I'm writing my code using a single mutex protecting the
>>>>> critical section.  But I forgot and didn't mutex-protect one method --
>>>>> what merely printed out the contents of a shared daa-structure, and
>>>>> when that printout coincided with a thread actually mutating the
>>>>> data-structure, I got a deadlock.  Not hard to track down, and I
>>>>> chided myself for being lax.
>>>>> 
>>>>> But the thing is, in Java (blecch!) I would have been able to use the
>>>>> "javacore" facility to get a full-thread stack-traceback, and could
>>>>> have used that to get a good idea of where my deadlock was.
>>>>> 
>>>>> I'm not saying that this is something ocaml should have, but I figured
>>>>> I'd ask: are others (who use threads in ocaml) wishing for something
>>>>> like this?
>>>>> 
>>>>> --chet--
>>>>> 
>>>>> 
>>>>> 
>>>>> --
>>>>> Caml-list mailing list.  Subscription management and archives:
>>>>> https://sympa.inria.fr/sympa/arc/caml-list
>>>>> Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
>>>>> Bug reports: http://caml.inria.fr/bin/caml-bugs
> 
> -- 
> Caml-list mailing list.  Subscription management and archives:
> https://sympa.inria.fr/sympa/arc/caml-list
> Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
> Bug reports: http://caml.inria.fr/bin/caml-bugs


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [Caml-list] try...finally , threads, stack-tracebacks .... in ocaml
  2013-04-11  8:48         ` Malcolm Matalka
@ 2013-04-11 16:43           ` Chet Murthy
  0 siblings, 0 replies; 14+ messages in thread
From: Chet Murthy @ 2013-04-11 16:43 UTC (permalink / raw)
  To: Malcolm Matalka; +Cc: Caml List


I'm going to answer your question, but I would note that this is sort
of immaterial.  There -will- be code that wants to use native threads
(e.g., -all- odbc code) and when you need to work with that, and do
high-concurrency things, you'll either need to come up with a complex
method of transferring work between your simulated threads (== monadic
threads) and your native threads, or you'll need to work with native
threads.  In commercial code, native threading is and has been the
rule for many years.  And if you're going to work with commercial
code, you can't afford to rewrite the world.

OK, now to your question:

In most RPC-compilers, the stubs and skeletons are written on the
assumption that on the client the calling thread will block until the
response is received.  Absent call/cc, there's no real way to change
that without changing the generated code.

--chet--

P.S. I'm not saying it's impossible.  I've hacked Thrift-generated
client code to make it usable in an "asynchronous" manner.  I just
don't have the time to go hacking the idl-compiler right now.

On Thursday, April 11, 2013 04:48:25 AM Malcolm Matalka wrote:
> Out of curiosity, in what way does Thrift impose threads?  Is it
> actually handling socket-layer stuff?


^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2013-04-11 16:43 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-04-10 22:16 [Caml-list] try...finally , threads, stack-tracebacks .... in ocaml Chet Murthy
2013-04-10 22:28 ` simon cruanes
2013-04-11  0:19   ` Francois Berenger
2013-04-10 23:35 ` Yaron Minsky
2013-04-10 23:37   ` Yaron Minsky
2013-04-11  6:36     ` Malcolm Matalka
2013-04-11  6:42       ` Chet Murthy
2013-04-11  7:11         ` Francois Berenger
2013-04-11  7:17           ` Chet Murthy
2013-04-11  8:04             ` Roberto Di Cosmo
2013-04-11  8:48         ` Malcolm Matalka
2013-04-11 16:43           ` Chet Murthy
2013-04-11 11:13         ` Thomas Gazagnaire
2013-04-11  6:25 ` Jacques-Henri Jourdan

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).