Re: [c++-pthreads] cancellation points report failure
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [c++-pthreads] cancellation points report failure



On Sat, 20 Dec 2003 10:54:44 -0800, Mark Mitchell <mark@xxxxxxxxxxxxxxxx> wrote:

>> Since it apparently isn't yet clear to everybody what I had suggested,
>> I'll outline it again:
>
> I think it's a great to see a tidy description of your idea.  It's good
> to get concrete proposals on the table.
>
> Jason (Merill), would you care to post a similar description of your
> preferred scenario?

The scenario I've been thinking of is:

 * The POSIX cancellation points can throw a cancellation exception.
 * C++ I/O functions can throw a cancellation exception.
 * C++ catch blocks work normally.
 * If a cancellation exception is destroyed, the cancellation request
   is re-entered, and acted on again at the next cancellation point.

This model doesn't work as well for pthread_exit or longjmp_unwind, since
they don't have predefined deferral semantics.  I'm somewhat inclined to
stay with calling terminate if we swallow an exit exception.

I just did some testing on Tru64: Evidently in their structured
exception handling model, finalizing a cancellation exception discards the
cancellation request, as Mark was suggesting; ditto for pthread_exit.  And,
interestingly, abort().  Testcase attached below.

The main problem with extending these semantics to C++ is the iostream code
which traps all exceptions.  I think this is a mistake in the design of
iostreams, but it seems likely to be a common mistake, and I feel strongly
that it shouldn't silently discard the cancellation request.  That would
almost certainly be an unintended side-effect.

Jason

#include <pthread.h>
#include <pthread_exception.h>
#include <stdio.h>

void *
tf (void *p)
{
  int c = 0;
  while (1)
    {
      TRY
        {
          ++c;
          if (c == 100)
            pthread_exit (NULL);
          else if (c == 200)
            abort ();
          write (1, ".", 1);
        }
      CATCH_ALL
        {
          write (1, "caught\n", 7);
        }
      ENDTRY
    }

  return NULL;
}

int
main (void)
{
  pthread_t t;
  while (1)
    {
      write (1, "creating\n", sizeof("creating\n")-1);
      if (pthread_create (&t, NULL, tf, NULL))
        break;
      if (pthread_cancel (t))
        break;
      if (pthread_join (t, NULL))
        break;
      break;
    }
  return 1;
}