From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Original-To: caml-list@sympa.inria.fr Delivered-To: caml-list@sympa.inria.fr Received: from mail2-relais-roc.national.inria.fr (mail2-relais-roc.national.inria.fr [192.134.164.83]) by sympa.inria.fr (Postfix) with ESMTPS id BF2A47EE51 for ; Thu, 11 Apr 2013 13:13:16 +0200 (CEST) Received-SPF: None (mail2-smtp-roc.national.inria.fr: no sender authenticity information available from domain of thomas.gazagnaire@gmail.com) identity=pra; client-ip=74.125.82.48; receiver=mail2-smtp-roc.national.inria.fr; envelope-from="thomas.gazagnaire@gmail.com"; x-sender="thomas.gazagnaire@gmail.com"; x-conformance=sidf_compatible Received-SPF: Pass (mail2-smtp-roc.national.inria.fr: domain of thomas.gazagnaire@gmail.com designates 74.125.82.48 as permitted sender) identity=mailfrom; client-ip=74.125.82.48; receiver=mail2-smtp-roc.national.inria.fr; envelope-from="thomas.gazagnaire@gmail.com"; x-sender="thomas.gazagnaire@gmail.com"; x-conformance=sidf_compatible; x-record-type="v=spf1" Received-SPF: None (mail2-smtp-roc.national.inria.fr: no sender authenticity information available from domain of postmaster@mail-wg0-f48.google.com) identity=helo; client-ip=74.125.82.48; receiver=mail2-smtp-roc.national.inria.fr; envelope-from="thomas.gazagnaire@gmail.com"; x-sender="postmaster@mail-wg0-f48.google.com"; x-conformance=sidf_compatible X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: ArQCACCaZlFKfVIwjWdsb2JhbABICIM8rzSSF4EDFg4BAQEBBwsLCRIGJIIfAQEEAScTBgEtCwEDAQsBBQUYDSEhEwEFAQoSBhMSCYdnAwkGBAifG48qhScnAwqJVwEFDIw3gR2BAy6CbGEDlR2DBIRihW+DOj+BWYJX X-IPAS-Result: ArQCACCaZlFKfVIwjWdsb2JhbABICIM8rzSSF4EDFg4BAQEBBwsLCRIGJIIfAQEEAScTBgEtCwEDAQsBBQUYDSEhEwEFAQoSBhMSCYdnAwkGBAifG48qhScnAwqJVwEFDIw3gR2BAy6CbGEDlR2DBIRihW+DOj+BWYJX X-IronPort-AV: E=Sophos;i="4.87,454,1363129200"; d="scan'208";a="12809995" Received: from mail-wg0-f48.google.com ([74.125.82.48]) by mail2-smtp-roc.national.inria.fr with ESMTP/TLS/RC4-SHA; 11 Apr 2013 13:13:16 +0200 Received: by mail-wg0-f48.google.com with SMTP id m15so1458354wgh.3 for ; Thu, 11 Apr 2013 04:13:16 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=x-received:sender:subject:mime-version:content-type:from :in-reply-to:date:cc:content-transfer-encoding:message-id:references :to:x-mailer; bh=89IDDMHuc9IpGceCvGCmmTqFClwoxaVo5yRZHeQB4+s=; b=z4tXiWu8FgvXo9IS0kCeSAKehQHZiHOyJ/ymrZP3/41l6ma/UA+kA0+Wyx535QBSyx 3Xp9ixKIbCFVKa0cAHeecNA/ijm9AMEsyV1mEmaj9dqoDWLaRG1/FZ144XjsmXc0f9Zo 5eFrkTBoBQK4A52u5RT3z3vt/1nRAIia5LWC8hNQMqdeKk9ooTW7bLTJkkM+U30djAlD jy8F5hR0kALQD2CbF+Qh6ojYOoB4REuEhkr9TXS3R8SSSz4ECSAf5juuvX8Qcfb7obDl DrpFRLsiT6/N5zq9rzYnFm2rrOxsqXR8KfazRN7ctx9Bf/PMj1i8sFdYw+do1JwA9OQ2 af5A== X-Received: by 10.180.72.228 with SMTP id g4mr32975165wiv.22.1365678796139; Thu, 11 Apr 2013 04:13:16 -0700 (PDT) Received: from [192.168.0.12] (gou06-3-88-170-165-56.fbx.proxad.net. [88.170.165.56]) by mx.google.com with ESMTPS id h10sm2730763wic.8.2013.04.11.04.13.14 (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Thu, 11 Apr 2013 04:13:15 -0700 (PDT) Sender: Thomas Gazagnaire Mime-Version: 1.0 (Apple Message framework v1085) Content-Type: text/plain; charset=us-ascii From: Thomas Gazagnaire In-Reply-To: <1725573.oORHJHkDHi@groupon> Date: Thu, 11 Apr 2013 13:13:12 +0200 Cc: Caml List Content-Transfer-Encoding: quoted-printable Message-Id: <961CE916-0EE5-4F88-B080-BA36824BF020@ocamlpro.com> References: <4989654.hHte10Um7f@groupon> <87obdld161.fsf@li195-236.members.linode.com> <1725573.oORHJHkDHi@groupon> To: Chet Murthy X-Mailer: Apple Mail (2.1085) Subject: Re: [Caml-list] try...finally , threads, stack-tracebacks .... in ocaml > 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 >=20 > 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. >=20 > 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? >=20 > --chet-- >=20 > 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. >>=20 >> /M >>=20 >> Yaron Minsky 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. >>>=20 >>> y >>>=20 >>> On Wed, Apr 10, 2013 at 7:35 PM, Yaron Minsky = =20 > wrote: >>>> Chet, are you sure that one looses the stack trace in this case? My >>>>=20 >>>> example using Core seems to preserve it. Here's the code: >>>> open Core.Std >>>>=20 >>>> let a () =3D let _ =3D "a" in raise Not_found >>>> let b () =3D let _ =3D "b" in a () >>>>=20 >>>> let c () =3D >>>>=20 >>>> let _ =3D "c" in >>>> protect ~f:b >>>>=20 >>>> ~finally:(fun () -> ()) >>>>=20 >>>> let d () =3D let _ =3D "d" in c () >>>> let () =3D d () >>>>=20 >>>> 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 >>>>=20 >>>> 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]. >>>>=20 >>>> This is from the Exn module in Core. >>>>=20 >>>> let protectx ~f x ~(finally : _ -> unit) =3D >>>>=20 >>>> let res =3D >>>>=20 >>>> try f x >>>> with exn -> >>>>=20 >>>> (try finally x with final_exn -> raise (Finally (exn, >>>> final_exn))); >>>> raise exn >>>>=20 >>>> in >>>> finally x; >>>> res >>>>=20 >>>> ;; >>>>=20 >>>> let protect ~f ~finally =3D protectx ~f () ~finally >>>>=20 >>>> On Wed, Apr 10, 2013 at 6:16 PM, Chet Murthy = =20 > 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. >>>>>=20 >>>>> let finally f arg finf =3D >>>>>=20 >>>>> let rv =3D try Inl(f arg) with e -> >>>>>=20 >>>>> Inr e >>>>>=20 >>>>> in (try finf arg rv with e -> ()); >>>>>=20 >>>>> match rv with >>>>>=20 >>>>> Inl v -> v >>>>> |=20 >>>>> | Inr e -> raise e >>>>>=20 >>>>> 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. >>>>>=20 >>>>> 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. >>>>>=20 >>>>> 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. >>>>>=20 >>>>> 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. >>>>>=20 >>>>> 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? >>>>>=20 >>>>> --chet-- >>>>>=20 >>>>>=20 >>>>>=20 >>>>> -- >>>>> 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 >=20 > --=20 > 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