This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Patch: sophisticated failed handling in obstack


With some effort, we can make the obstack failed handling interface
more sophisticated: by adding obstack-specific failed handler and user
provided data, several obstacks can work together without bothering
each other.

Suppose we have two obstacks in a program, which react differently to
allocation failures.  The first one wants to exit the program when
failure happens, but the second one wants to longjmp to somewhere in
order to recover from the failure.  With only one global failed
handler -- obstack_alloc_failed_handler, we cannot distinguish the
caller in the handler in an easy way.  So implementing this behavior
is difficult.

However, we can solve this by adding failed handlers to obstack
objects.  When allocation fails, we take a look at the obstack itself.
If there is a failed handler in it, we call it; otherwise, we call the
global obstack_alloc_failed_handler as before.

Now suppose we have two obstacks in a program, both of them want to
recover from the failure by longjmp'ing in failed handlers.  Since we
call failed handlers without arguments, the jumping destination cannot
be decided easily, even if the handlers are obstack-specific.

So it is necessary to add user provided data to obstack object to make
this easy.  When allocation fails, we pass the user provided data to
failed handlers, so that each handler knows where to jump in certain
cases.

Here is an example of how to use the improved obstack interface:

/* EXAMPLE BEGINNING */

/* An obstack failed handler.  DATA is filled in some obstack and
  passed to the handler.  To convert DATA into a jmp_buf for example,
  we can decide the jumping destination easily.  */

void
an_obstack_failed_handler (void *data)
{
 jmp_buf *env = (jmp_buf *) data;

 longjmp (*env, 1);
}

/* This function uses a jmp_buf and an obstack to support its
  complicated operations.  It returns 0 on success and -1 on failure,
  but will not exit in either case.  With the improved obstack
  interface, this function can do its job without depending any
  global status of the program.  */

int
func1 (void)
{
 struct obstack obstack;
 jmp_buf func1_env;
 int have_errors = 0;

 /* Setting up the jmp_buf.  */
 if (setjmp (func1_env))
   {
     /* Put the failed handler and the jmp_buf into the obstack.  */
     obstack_init_sophisticatedly (&obstack,
                                   an_obstack_failed_handler,
                                   &func1_env);

     /* Complicated operations...  */
   }
 else
   /* OK, we finish with errors.  So let's set the flag and let the
      caller know about it.  */
   have_errors = 1;

 obstack_free (&obstack, NULL);
 return have_errors ? -1 : 0;
}

/* EXAMPLE END */

The above example shows an obstack inside a function.  But in practice
we usually put obstacks in C struct's but not functions.  In such a
case, the improved interface can make these objects independent to
global variables, which is usually important nowadays.

The patch to this improvement is attached in this message.  For
compatibility issues, note that when
OBSTACK_SOPHISTICATED_FAILED_HANDLING is not #define'd, the interface
is exactly as before.  If OBSTACK_SOPHISTICATED_FAILED_HANDLING is
#define'd, except initializing and failed handling, the interface is
still unchanged.  At last, the behavior of obstack_init in the new
interface and the old failed handling function print_and_abort is also
not changed.  So there is no non-compable changes.

Please review the change and consider add this patch to obstack.  I
would like to do any work to ensure the robustness of the improvement.
Thanks.

Regards,
Guanpeng Xu

_________________________________________________________________
Express yourself instantly with MSN Messenger! Download today it's FREE! http://messenger.msn.click-url.com/go/onm00200471ave/direct/01/

Attachment: obstack.diff
Description: Binary data


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]