Hi Phil:

Here is further discussion of what you have said as opposed to the
error report I sent you in my previous post concerning your 3rd
iteration.

Do keep in mind the possibility for the future that the memory
allocation part of your commits are worthwhile in their own right and
could be finished and landed on master much sooner than the rest of
your commits that are concerned with implementation of C exception
handling and use of that for handling our errors.

I suggested in my big e-mail to you early this week (Mon, 17 Jul 2017
14:59:00 -0700 (PDT)) concerning your second iteration a method of doing
this using a list of plstream heap pointers.  Please respond to that
suggestion.

Also please respond to my suggestion (with appropriate code changes
while I handle the CMake part) in that e-mail concerning

#define PL_IMPLEMENT_EXCEPTION_HANDLING and
#ifdef PL_IMPLEMENT_EXCEPTION_HANDLING

On 2017-07-22 22:47+0100 Phil Rosenberg wrote:

[in that same e-mail] You asked why every API call required a PLTRY block. You 
are correct
that actually they don't. Every API call that may result in a call to
plexit needs a PLTRY block.

I initially didn't understand this explanation, but after _much_ too
long a time considering various scenarios to explain my point of view
the light finally dawned. Exception handling does not allow you to
transfer control to arbitrary places in the code (a stupid assumption
I was making). Instead, it merely allows you to unwind the call graph
from the plexit call (in this case that is the only current use of
PLTHROW in our source code) to return control to a routine potentially
far up the call stack from there such as _any_ of the public API
routines (as you said) that have a possible call to plexit somewhere
lower down on their call graph.

So sorry for my previous noise on this sub-topic, but
now we are finally on the same page in this regard, I have some
further questions and comments about your implementation of
exception handling and how you are using that exception handling
to deal with bad errors.

* If you miss putting a PLTRY and PLCATCH block in one of those public
  API cases where a potential call to plexit is somewhere lower on the
  call graph, then what does the current code do?  Does it simply
  crash (i.e., is that the potential cause of the serious issues I
  have reported to you in my previous post) or do you handle that
  internal error case by, e.g., emitting an "internal error: unhandled
  exception" message followed by an exit?

* What happens when an external application calls a "first" public API
  which has another "second" public API lower down in its call graph
  and even further down on the call graph of that second API occurs a
  potential call to plexit? Then if plexit is called that will PLTHROW
  control to the catch block of that second API rather than the first.
  So for this particular call graph case for the first API this second
  API needs to PLTHROW control to that first PLCATCH block rather than
  simply returning.  And, of course, since that second API is
  sometimes called directly from external applications and libraries
  without anything higher in the call graph with a PLCATCH block, it
  cannot PLTHROW all the time without sometimes running
  into the internal error discussed above.  So how are you going to figure out
  when to PLTHROW in a public API PLCATCH block and when not to PLTHROW?
  Or is that case already automatically taken care of by your present code
  (e.g., by each PLTRY macro incrementing a library status flag
  so that the PLCATCH macro can check that flag to see if there
  is a PLCATCH block higher in the call graph that it should PLTHROW
  to)?

* Shouldn't your current plexit call plend (like the master branch
  version does) to shut down the library?  See further discussion
  below concerning this suggestion.

* I also suggest you should implement a PLplot library state variable
  (let's call it plplot_library_status) that is initialized to 0 (good
  status) when the library is initialized but set to 1 (bad status) by
  plexit. Then follow up by implementing a c_plstatus() public API
  that returns the value of library_status and which emits a message
  such as ("library had bad error so it had to be shut down.  To use
  it again you need to initialize the library by calling one of the
  plinit family of routines".) Then an external application could call
  c_plstatus to check on the status of the library after any call to
  our public API and act accordingly.

  Or it could be sloppy about that (i.e., our standard C examples
  might only call plstatus in one example to make sure it works). In
  which case after the library is shutdown (see above) by an internal
  call to plexit there would be a blizzard of further plabort (due to
  plsc->level being 0) and plexit messages after the first one because
  of that library shutdown.  But there would be no call to the dreaded
  exit routine so there is at least the chance that the external
  application will survive that sloppiness.  And if plexit does not
  call plend, I think the chances of an external application
  encountering a showstopper error are much worse.

However, if we just have a policy that
every API call must have a PLTRY block then it makes it easy to ensure
nothing gets missed. But perhaps this is overkill. A number of
functions in plcore.c, particularly the "get" type ones are very
simple and would never call plexit. I'm happy to take advice on where
the balance should lie?

One other issue at the moment. I currently output a warning when
plfree is called on a pointer that is not being managed by the
PLStream. At present this will include all plfree calls made in
plend/plend1 and can include memory allocated by the contour routines.
The reason for this is due to the following chain of events
1) These bits of memory get allocated by plalloc in an API call
somewhere (e.g cmap0).
2) On exit from the API call plfreeall gets called
3) plfreeall spots the allocated memory that wasn't freed and checks
all the pointers that belong to the PLStream
4) It finds that the pointers belong to PLStream and need to not be
freed. It therefore stops tracking them.
5) In plend1 plfree is called on the pointer. plfree cannot see the
pointer in the list of tracked pointers so issues a warning.

There are a few options for dealing with this, but I haven't decided
which to use. For now my apologies for the list of warnings.


I am frankly out of gas, and this is already a pretty long e-mail
so I will leave it to you to decide on the above topics unless
someone else here wants to comment.

Anyhow, after I get some sleep, I am looking forward to your further
comments on (a) my error report for interation 3, and (b) what I have
had the energy to discuss above.

Alan

__________________________
Alan W. Irwin

Astronomical research affiliation with Department of Physics and Astronomy,
University of Victoria (astrowww.phys.uvic.ca).

Programming affiliations with the FreeEOS equation-of-state
implementation for stellar interiors (freeeos.sf.net); the Time
Ephemerides project (timeephem.sf.net); PLplot scientific plotting
software package (plplot.sf.net); the libLASi project
(unifont.org/lasi); the Loads of Linux Links project (loll.sf.net);
and the Linux Brochure Project (lbproject.sf.net).
__________________________

Linux-powered Science
__________________________

------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
Plplot-devel mailing list
Plplot-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/plplot-devel

Reply via email to