All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Yoshinori K. Okuji" <okuji@enbug.org>
To: The development of GRUB 2 <grub-devel@gnu.org>
Subject: Re: problem in usage of grub_errno...
Date: Sat, 10 Dec 2005 14:11:11 +0100	[thread overview]
Message-ID: <200512101411.11612.okuji@enbug.org> (raw)
In-Reply-To: <439AA87B.9050607@nic.fi>

On Saturday 10 December 2005 11:05 am, Vesa Jääskeläinen wrote:
> Changing coding guide of using grub_errno we could probably get this
> issue "working". But then there is still problem with lost error
> messages if subsequent code fails with real error.
>
> If we just zero out grub_errno in code before printing out error(s).
> Then the actual error message will get lost. So it is important not to
> zero out spuriously grub_errno.
>
> Good way of checking for errors could be like:
> --
> grub_errno_t rc;
>
> rc = function_that_could_fail ();
> /* do some stuff here.  */
> if (rc)
>   return rc;

Please do not change it in this way. The error subsystem of GRUB is based on 
the idea of exceptions, that is to say, passing an error to higher levels 
until it is caught explicitly. This is similar to C++, Java, Python or Ruby. 
Unfortunately, C does not support exceptions directly, so we must emulate it. 
So, what we must do is not to ignore an error where it happens.

I use Python as an example. Suppose this code:

def foo():
  bar()

def bar()
  baz()
  print 'bar'

def baz()
  raise RuntimeError, 'baz'

foo()

When executing this, Python does not print 'bar', because the exception raised 
by baz is not caught by bar, and the control is immediately transferred to 
foo.

In C, to emulate this behavior, we must do like this:

void
foo (void)
{
  bar ();
}

void
bar (void)
{
  baz ();
  if (grub_errno != GRUB_ERR_NONE)
    return;
  grub_printf ("bar\n");
}

void
baz (void)
{
  grub_error (GRUB_ERR_SOMETHING, "baz");
}

In other words, if you ignore an error set by calling a function and pass the 
control to another, it violates the semantics. So, strictly speaking, you 
must choose either of these when an error is set:

- deciding to ignore the error explicitly by setting GRUB_ERRNO to 
GRUB_ERR_NONE

- handling the error by returning to the higher level or dealing with the 
error  locally (e.g. printing the error)

We (at least I) sometimes violate this rule by intention when knowing that it 
is safe to ignore an error, simply because it is too heavy to deal with 
errors all the time.

In your situation, things are a bit complicated. In my opinion, all you should 
do is to save error information in a temporary place and reset it afterwards. 
For example, you can define a function like this:

void
grub_error_push (void)
{
  /* Push the current error in a stack and clear GRUB_ERRNO.  */
  ...
}

void
grub_error_pop (void)
{
  /* Pop the previous error and set GRUB_ERRNO.  */
  ...
}

I don't know if this should be stack-based or flat. For example, you can 
allocate space in a function and pass the pointer to a function which saves 
current error information. In this case, functions should be named 
grub_error_save and grub_error_restore.

The difficulty is that it is not very safe to use a heap to allocate space to 
store error information, because such a memory allocation can generate 
another error (due to memory shortage). The possibility is low, but we must 
still consider it.

One way is to allocate such space in advance. For example, if we use the 
stack-based approach (personally I prefer this for consistency), instead of 
allocating space dynamically, we can allocate it statically. That is, at 
linking time or at initialization time. This way limits the maximum number of 
slots arbitrarily, but it should be enough for the reality (e.g. 10).

What do you think?

Okuji




  reply	other threads:[~2005-12-10 13:11 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2005-12-09 21:58 problem in usage of grub_errno Vesa Jääskeläinen
2005-12-09 22:29 ` Marco Gerards
2005-12-10 10:05   ` Vesa Jääskeläinen
2005-12-10 13:11     ` Yoshinori K. Okuji [this message]
2005-12-10 20:12       ` Vesa Jääskeläinen
2005-12-17 17:40         ` Vesa Jääskeläinen
2005-12-17 22:59           ` Tomáš Ebenlendr
2005-12-17 23:16             ` Vesa Jääskeläinen
2005-12-19  5:15               ` Joel Buckley
2005-12-19 15:35                 ` Vesa Jääskeläinen
2005-12-19  8:37               ` Tomáš Ebenlendr
2005-12-19 15:42                 ` Vesa Jääskeläinen

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=200512101411.11612.okuji@enbug.org \
    --to=okuji@enbug.org \
    --cc=grub-devel@gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.