This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC 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]

Re: [3.3] Followup to C++ forced unwinding


On Wed, 2003-04-30 at 19:46, Ulrich Drepper wrote:
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
> 
> Mark Mitchell wrote:
> 
> > I know that POSIX doesn't endorse this particular behavior, and that
> > code that relies on it is non-portable -- but so is unwinding the
> > stack.  You could even reasonably argue that unwinding the stack is a
> > violation of the POSIX standard; it doesn't say that you do that.
> 
> You still don't get it.  This is not about violating POSIX or not.  This
> is about implementation (not specifications) relying on the program
> never to return from the dead.  A very reasonable assumption.  Once
> canceled the only way out is to die after all cleanup handlers are
> called.  Entire implementations of thread libraries depend on this and
> this cannot be changed.

I think we've now got (at least a temporary) resolution to this problem,
in the form of my suggestion as augmented with Jason's very clever idea.

You seem to be saying that:

(1) It is safe to unwind the stack, calling destructors and running code
inside catch-clauses.  Furthermore, it is safe for that code to access
variables in the stack frames which contain it, call other functions
(possibly making the stack bigger than it was before), make system
calls, and so forth, with the possible exceptions of calling
pthread_exit (forbidden by POSIX), calling longjmp, and other similar
corner-cases.

(2) It is, however, unsafe to execute code that is not within a
destructor or a catch-clause.

I know that it should be easy even for someone of my admittedly limited
intelligence to figure out why this should be the case, but, as you've
pointed out, despite your multiple explanations, I'm just not
understanding.  

Maybe you could point me at the source code for one of these thread
library implementations where (1) holds, but (2) does not?

I can't even figure out why this wouldn't work:

/* This is the function that is first called in the new thread.  */

void __thread_start (void *(*fp)(void *), void* arg)
{
  void* r;
  r = (*fp)(arg);
  if (__thread_has_been_cancelled ()) {
    /* This thread was cancelled, but returned normally.
       
       Perhaps, during the stack-unwinding for the cancellation
       exception, a catch-clause did not rethrow the exception.

       Since we got here, the stack is fully unwound and all
       cleanups registered with pthread_push_cleanup have been run.  

       If there is some data structure that was created when 
       cancellation occurred, get rid of it now.  For example, 
       maybe cancellation was implemented by a signal, and since
       the stack unwinding didn't ever terminate, there's some
       signal-stack lying around that we need to clean up.  Of 
       course, this could have been handled when the exception 
       object was destroyed via Jason's idea... */
  }
  return r;
}

-- 
Mark Mitchell <mark@codesourcery.com>
CodeSourcery, LLC


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