Is there any method that causes whole stack frame unwinding in C++? (except using exception)

StackOverflow https://stackoverflow.com/questions/9287771

  •  29-04-2021
  •  | 
  •  

Вопрос

I've been writing a continuation - in specific, coroutine - library. It's similar to std::thread (except that it's cooperative) - each execution contexts are represented in continuation object.

The problem is about continuation object destruction. If dtor for the continuation object is invoked while the execution context haven't exited gracefully, it should be forced to be closed by the context destroying the object.

In this way, every C++ object in the stack frame won't be destroyed properly. This may not be a pleasant situation for anyone - So I decided to find a solution.

At the first time, I thought to use exception to unwind stack frame like below. (Note that below is just flawed psuedo-code.)

coroutine::~coroutine()
{
    status = FORCED_EXIT;
    switch_to(*this);
}

void coroutine::yield(coroutine& other_coroutine)
{
     // switch to other context, halt until invocation by other context
    switch_to(other_coroutine);

    if (status_ != FORCED_EXIT) {
        return; // resume
    } else {
        throw ContextClosingException;
    }
}

void coroutine::entrypoint()
{
    try {
        entry_function_();
    } catch(ContextClosingException& e) {
        switch_to(caller_coroutine);
    }
}

However, I've found some critical flaw. Any user code that "swallow exception" as below will completely break the assumption of cooperative scheduling.

try {
    ...
} catch(...) { // ContextClosingException 
    // do nothing, just swallow exception.
}

So I need to find other way to invoke stack unwinding (or any other way to destruct stack object in the continuation). Standard conformance way would be nice - but the continuation implementation itself is dependent on platform specific API, so non-portable way would be acceptable. (I'm using win32)

Это было полезно?

Решение

There's nothing in the C++ standard that allows unwinding the stack except exceptions. Coroutines (or support for corountines) may be proposed post C++11 (talked about during the Going Native conference).

You'll have to use OS-specific C calls (if any exist and I don't think so), but most likely you're on your own with ASM. You may have a look at the boost.context library for a sample solution.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top