Boost logo

Boost :

Subject: Re: [boost] [context review]
From: Artyom (artyomtnk_at_[hidden])
Date: 2011-03-25 08:29:19


>
> The first issue is that the destructor of the context class will (at
> least by default) happily destroy the stack. This unfortunately will
> leak any resource owned by any object on the stack; This is not unlike
> destroying an allocator before having destroyed all allocated object.
>

I want to add a small point.

When I reviewed Boost.Context I had thought at the begging
about it but then I realized that it is very problematic requirement.

The only portable way to abort stack unwinding is to throw
an exception and catch it at top level.

     context_1.jump_to(context_2);
        // throws something like fiber interrupted.
        // if stack is destroyed.

Actually it is quite problematic, for example what if
there is a code that does

  try {
     ...
     context_1.jump_to(context_2);
     ...
  }
  catch(...) {
     // Ignore all errors
  }

The stack would not be unwinded and the destructor of the
stack would be stuck in execution of current destroyed thread.

Think of thread cancellation, for example on Linux
the program below unwinds C++ stack only of the
throw below exists, if it commented out the
program aborts with
  
  ctor
  start
  FATAL: exception not rethrown

If throw exists

  ctor
  start
  dtor

As expected.

FreeBSD it does not unwind the stack at all,
and it is not required by the standard
so you would see

   ctor
   start

#include <pthread.h>
#include <iostream>
#include <unistd.h>

void *thread(void *)
{
  {
    struct test {
      test() { std::cerr << "ctor" << std::endl; }
      ~test() { std::cerr << "dtor" << std::endl; }
    } tester;

    std::cerr << "start" << std::endl;
    for(int i=0;i<1000;i++) {
      try {
        // canelation poit
        usleep(10000);
      }
      catch(...) {
        throw;
        // If commented progam
        // aborts
      }

    }
    std::cerr << "end" << std::endl;
  }
}

int main()
{
  pthread_t p;
  pthread_create(&p,0,thread,0);
  usleep(1000000);
  pthread_cancel(p);
  pthread_join(p,0);
  return 0;
}

So leaving this to higher level abstraction would be
correct because there is not simple or portable
way to do this because you can't force program to
ignore catch(...) {}

My small comments.

Artyom

      


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk