From: Andrew R. <and...@us...> - 2009-09-24 20:35:15
|
On Thu, Sep 24, 2009 at 02:04:50PM -0500, Hezekiah M. Carty wrote: > On Thu, Sep 24, 2009 at 12:24 PM, Hazen Babcock <hba...@ma...> wrote: > > Hezekiah M. Carty wrote: > >> > >> On Thu, Sep 24, 2009 at 10:16 AM, Hazen Babcock <hba...@ma...> wrote: > >>> > >>> Hezekiah M. Carty wrote: > >>>> > >>>> On Wed, Sep 23, 2009 at 10:41 PM, Hazen Babcock <hba...@ma...> > >>>> wrote: > >>>>> > >>>>> Hezekiah M. Carty wrote: > >>>>> If you are using a language that supports exceptions and callbacks from > >>>>> C > >>>>> you can override the PLplot's default exit() behavior. > >>>> > >>>> I attempted that this evening with OCaml after adding plsabort and > >>>> plsexit support to the language bindings. ??Unfortunately, I found that > >>>> plsexit and plsabort do not override the plabort and plexit behavior. > >>> > >>> Can you write your callbacks so that they never return control to PLplot? > >> > >> That is a good point. ??I just tested this, and at least in the case of > >> OCaml if the callback raises an exception then control does not return > >> to PLplot. ??Do you know if this is safe? ??I don't want to create > >> hard-to-debug leaks and corner cases with something like this. ??A > >> simple test which raises exceptions on calls to plabort, catches the > >> exceptions and repeats this process multiple times seems to come out > >> valgrind-clean on my system, so my initial impression is that this is > >> safe for at least some of the plabort calls in PLplot. > >> > >> plsexit may be less clear as a grep through src/ shows that it is > >> almost always used for out of memory/failed malloc calls. ??Different > >> assumptions may be made when plexit is called, with a greater chance > >> of memory leaks if the program continues rather than exits. > >> > >> This does not address the use of exit() in other areas of PLplot, but > >> as long as this approach does not create memory leaks it does address > >> my immediate concern. > > > > I don't really know whether this is actually safe with regards to memory > > leaks. I'd guess not because I'd imagine that somewhere there is now a stack > > of commands waiting for a return that is never going to come. Maybe the OS > > detects this and cleans up this defunct code path? Maybe I have no idea what > > I am talking about? The test I can think of would be to generate a few > > thousand exceptions and see if the memory consumption increases and/or you > > get a stack overflow. > > I have attached the OCaml code I used to test this for illustration. > If anyone else wants to run this test, I'd recommend reducing the > number of iterations (the "for i = 1 to n" line, where "n" is the > number of iterations). The current value of 100_000 takes a while to > run. The call to plabort happens in this example because > Quick_plot.lines attempts to draw each line a different color. The > example's call to Quick_plot.lines attempts to plot 40 lines and > PLplot's devices generally allocate <= 16 colors by default. > > I ran this under valgrind with n = 10 and errors were reported. > Running the program on its own and monitoring the process's RAM use > for n = 100_000, the memory use fluctuated due to freed/allocated > memory but the peak memory use stayed constant throughout the > program's execution. > > For a sample of 1 (OCaml 3.11.1, Ubuntu 9.04 64bit on an Intel > Core2Duo CPU, Linux kernel 2.6.31) this does not seem to cause a > memory leak or stack overflow. > > Hez > > -- > Hezekiah M. Carty > Graduate Research Assistant > University of Maryland > Department of Atmospheric and Oceanic Science > open Plplot > open Printf > > exception Plot_abort of string > > let () = > plsabort (fun s -> raise (Plot_abort (sprintf "abort: %s" s))); > let m = Array.make 40 (Array.init 40 float_of_int) in > let xs = Array.to_list m in > let ys = xs in > for i = 1 to 100_000 do > try > Quick_plot.lines ~device:(Plot.Other_device "null") (List.combine xs ys); > with > | Plot_abort s -> > plspause false; > plend (); > done; > () plexit calls plend _after_ the exit handler is called, and so if the exit handler throws an exception plplot will not call plend to tidy up and free memory. Provided that you do this yourself in your handler then you _should_ be ok. Of course, we would need to check all code paths with plexit in to make sure they don't leave any locally allocated memory unfreed. I don't know whether this is the case. It has probably never been thoroughly tested since we only tend to run valgrind on the examples which are set up not to generate any errors. Andrew |