gEDA-dev: [RFC] Blog: Error reporting & handling in libgeda

Peter TB Brett peter at peter-b.co.uk
Tue Nov 27 18:24:35 EST 2007


Hi folks,

At long hiatus, I've produced another lengthy blog post on libgeda 
development.  It's at 

http://www.peter-b.co.uk/blog/2007/11/error-reporting-handling-in-libgeda.html

and reproduced below for your convenience.  I'd be interested in your 
comments.

Regards,

                            Peter



Error reporting & handling in libgeda
=====================================

In general, libgeda kills the process without warning far too often. This is a 
bad thing for a library to do; in particular, it's very bad to do it just 
because someone passed some bad data in. The libgeda doesn't make any attempt 
to hide how the data structures are organised, and thus we have to assume 
that user code will make use of this knowledge to try and hack them directly.

My pondering of this problem over the last couple of days has lead me to think 
up four basic rules to consider when working out how to handle errors 
occuring in libgeda code:

1. If possible, succeed.

2. If failure is inevitable, fail gracefully.

3. If normal operation may result in failure, use GError.

4. Assume that libgeda works.

Of course, some of these need a little explanation as to their interpretation 
and why they make sense.

Firstly, "If possible, succeed." This seems obvious, but actually has some 
subtlety. What I mean here is that if there's a sensible, clean way of 
carrying on despite a problem, you should do so. This only really applies to 
user-facing code, as code which can't be called from outside libgeda really 
should have had its inputs checked by the calling function already. However, 
since all of libgeda's code is user-facing -- we don't have any private 
headers or the like -- this point is rather moot. In addition, "succeeding" 
doesn't preclude printing messages to the effect of, "Someone's playing silly 
buggers but I'm going to try my best anyway." g_critical() should be used for 
this. One example would be when an unknown object type is encountered; at the 
moment, libgeda often kills the program by calling g_assert_not_reached(), 
when often it would be valid to continue by logging a critical message and 
then skipping over the offending object.

Secondly, "If failure is inevitable, fail gracefully." Failing gracefully 
requires no dangerous side-effects from the failure. If possible, the system 
should be returned to its prior state. This often requires that user data 
needs to be checked before doing anything destructive, possibly at the 
expense of some CPU time.

GError is a nice mechanism in that it allows errors to be ignored if 
necessary. A good example of when it should be used would be in code which 
reads and writes files; because GLib's file access code already uses GError 
extensively, this would not be hard to implement.

Finally, "Assume that libgeda works." Similarly to rule #1, what is meant here 
is that libgeda functions should check their own behaviour. If they do so, 
there is no need for libgeda functions which call them to check again -- it's 
a waste of CPU time and developer effort.

So, given the above points, when is it appropriate to use g_assert()? It would 
not be appropriate to use it to check the arguments passed to a function, but 
it would be valid to use it to check that the function has successfully done 
what it is supposed to before returning a result. For instance, when a 
complex algorithm is in use, putting some assertions in to make sure that the 
algorithm actually does what you think it does might be a very good idea.
Of course, this has lead to a number of action items in terms of libgeda 
refactoring:

- Cleaning up uses of g_assert() in libgeda, and replacing them with
  g_critical() logging and graceful failure where possible. I've already made
  a start on this.

- Moving all of the file handling code to use GError. This will allow gschem
  to show a message dialog when a file operation fails, rather than forcing
  the user to look at the log window or at the console.

- In the medium term, moving all of libgeda to use the GLib logging API (of
  which g_critical() is part) will allow the development of a shiny new gschem
  log window which allows logging at different levels with colour coding of
  criticality. This would be nice.

- Ideally, the error messages used for GErrors emitted from libgeda should be
  translated. This means libgeda will need to use gettext.

As usual, I'd be interested to hear peoples' thoughts on this. Please let me 
know on the -dev list or by e-mail.

-- 
Peter Brett

Electronic Systems Engineer
Integral Informatics Ltd
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: This is a digitally signed message part.
Url : http://www.seul.org/pipermail/geda-dev/attachments/20071127/2e36408f/attachment.pgp 


More information about the geda-dev mailing list