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 mail3-relais-sop.national.inria.fr (mail3-relais-sop.national.inria.fr [192.134.164.104]) by sympa.inria.fr (Postfix) with ESMTPS id 26A327EE51 for ; Thu, 11 Apr 2013 10:48:29 +0200 (CEST) Received-SPF: None (mail3-smtp-sop.national.inria.fr: no sender authenticity information available from domain of mmatalka@gmail.com) identity=pra; client-ip=209.85.215.49; receiver=mail3-smtp-sop.national.inria.fr; envelope-from="mmatalka@gmail.com"; x-sender="mmatalka@gmail.com"; x-conformance=sidf_compatible Received-SPF: Pass (mail3-smtp-sop.national.inria.fr: domain of mmatalka@gmail.com designates 209.85.215.49 as permitted sender) identity=mailfrom; client-ip=209.85.215.49; receiver=mail3-smtp-sop.national.inria.fr; envelope-from="mmatalka@gmail.com"; x-sender="mmatalka@gmail.com"; x-conformance=sidf_compatible; x-record-type="v=spf1" Received-SPF: None (mail3-smtp-sop.national.inria.fr: no sender authenticity information available from domain of postmaster@mail-la0-f49.google.com) identity=helo; client-ip=209.85.215.49; receiver=mail3-smtp-sop.national.inria.fr; envelope-from="mmatalka@gmail.com"; x-sender="postmaster@mail-la0-f49.google.com"; x-conformance=sidf_compatible X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: ArQCAOV3ZlHRVdcxjWdsb2JhbABQgmVXrzSSF4EBFg4BAQEBBwsLCRIGJIIfAQEEAScZARsSCwEDAQsGBRgJBCEPAQQNAhEBBQEKGBMSCYdmAQMJBgELn3SML4J7hQYKGScDClmIfgEFDIw3glMHg0EDlR2DBIpRgzo/hEo X-IPAS-Result: ArQCAOV3ZlHRVdcxjWdsb2JhbABQgmVXrzSSF4EBFg4BAQEBBwsLCRIGJIIfAQEEAScZARsSCwEDAQsGBRgJBCEPAQQNAhEBBQEKGBMSCYdmAQMJBgELn3SML4J7hQYKGScDClmIfgEFDIw3glMHg0EDlR2DBIpRgzo/hEo X-IronPort-AV: E=Sophos;i="4.87,454,1363129200"; d="scan'208";a="10570865" Received: from mail-la0-f49.google.com ([209.85.215.49]) by mail3-smtp-sop.national.inria.fr with ESMTP/TLS/RC4-SHA; 11 Apr 2013 10:48:28 +0200 Received: by mail-la0-f49.google.com with SMTP id fs12so1223609lab.8 for ; Thu, 11 Apr 2013 01:48:27 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=x-received:from:to:cc:subject:references:date:in-reply-to :message-id:user-agent:mime-version:content-type; bh=j4ueU2k0V7Dk/XEZeq9E5deXHymSSoHnMGra8bMwv1Y=; b=i6NdV6wSU6uvINdn98yeszk4Rtr5dxdVoEEb4iE9niSQovD14nHFTpNFCzUdLowvZ6 EFT7lQxIV/yJYqo6D9mTnv/FFErVCBQuePuIE+5MggBSQhAkYoeJNfTJw6ZeyLO0RivE KqVIsSvLXkIk++FkPM8PKeS6Cqa2RC9w98SFXpZp5I4RggEQfHbeIx240E/k1Zejvg41 NTg5/63SUnsLngg4pRArCEGMWWLoAxa3LtZdEzYoNmyfzAUWApDX5CfRrcNJytKrSu6N pbD1gw+9576igV6XndkZiuvfZXyfRSk9C72s2J0CLcZsorTuPXSnJvgtEm/Jd8gylsVm 70mQ== X-Received: by 10.112.34.200 with SMTP id b8mr2871855lbj.3.1365670107262; Thu, 11 Apr 2013 01:48:27 -0700 (PDT) Received: from localhost ([2a01:7e00::f03c:91ff:fedf:4d21]) by mx.google.com with ESMTPS id p1sm1250201lae.0.2013.04.11.01.48.26 (version=TLSv1.1 cipher=RC4-SHA bits=128/128); Thu, 11 Apr 2013 01:48:26 -0700 (PDT) From: Malcolm Matalka To: Chet Murthy Cc: Caml List References: <4989654.hHte10Um7f@groupon> <87obdld161.fsf@li195-236.members.linode.com> <1725573.oORHJHkDHi@groupon> Date: Thu, 11 Apr 2013 04:48:25 -0400 In-Reply-To: <1725573.oORHJHkDHi@groupon> (Chet Murthy's message of "Wed, 10 Apr 2013 23:42:47 -0700") Message-ID: <87fvyxcv1i.fsf@li195-236.members.linode.com> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/24.2 (gnu/linux) MIME-Version: 1.0 Content-Type: text/plain Subject: Re: [Caml-list] try...finally , threads, stack-tracebacks .... in ocaml 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 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 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 > 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 > 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