From: Chet Murthy <murthy.chet@gmail.com>
To: Caml List <caml-list@inria.fr>
Subject: Re: [Caml-list] try...finally , threads, stack-tracebacks .... in ocaml
Date: Wed, 10 Apr 2013 23:42:47 -0700 [thread overview]
Message-ID: <1725573.oORHJHkDHi@groupon> (raw)
In-Reply-To: <87obdld161.fsf@li195-236.members.linode.com>
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
next prev parent reply other threads:[~2013-04-11 6:43 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-04-10 22:16 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 [this message]
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
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1725573.oORHJHkDHi@groupon \
--to=murthy.chet@gmail.com \
--cc=caml-list@inria.fr \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox