LINUX.ORG.RU

C++ и исключение abi::__forced_unwind

 ,


0

3

Вопрос про исключение abi::__forced_unwind.

Почему в Linux оно есть, а в FreeBSD, например, нет?

Вот пример кода. Что бы не получать «FATAL: exception not rethrown» приходится собирать с условной компиляцией.

Как это обойти и из-за чего оно вообще возникает?

#include <iostream>
#include <functional>
#include <vector>

#include <pthread.h>
#include <signal.h>
#include <unistd.h>
#include <string.h>

#ifdef __linux__
#include <cxxabi.h>
#define __catch_all__ catch (abi::__forced_unwind&) { throw; } catch (...)
#else
#define __catch_all__ catch (...)
#endif

bool test_proc(const size_t &nom)
{
    std::cerr << nom;
    sleep(1);
    return true;
}

class threads
{
    public:
        typedef
            struct
            {
                pthread_t pid;
                size_t nom;
            }
            item_type;
        typedef
            std::function<bool(const size_t &nom)>
            proc_type;

    private:
        static std::vector<item_type> items;
        static proc_type proc;

        static void *inner_proc(void *data);
        static void interrupter(int signum);

    public:
        static void start
            (const proc_type &proc, const size_t &count);
        static void stop(void);
};

threads::proc_type threads::proc = threads::proc_type();

std::vector<threads::item_type> threads::items = std::vector<threads::item_type>();

void *threads::inner_proc(void *data)
{
    if (threads::proc)
    {
        auto item = (threads::item_type *) data;
        for (;;)
        try
        {
            threads::proc(item->nom);
        }
        __catch_all__
        {
        }
    }
    return NULL;
}

void threads::interrupter(int signum)
{
    signum = signum;
    threads::stop();
}

void threads::start(const proc_type &proc, const size_t &count)
{
    threads::proc = proc;
    threads::items.resize(count);
    if (!count) return;
    size_t nom = 0;
    for (auto &i : threads::items)
    {
        i.nom = nom;
        pthread_create(&i.pid, NULL, threads::inner_proc, &i);
        nom++;
    }
    static struct sigaction sa;
    memset(&sa, 0, sizeof(struct sigaction));
    sa.sa_handler = threads::interrupter;
    sigaction(SIGINT, &sa, NULL);
    pthread_join(threads::items[0].pid, NULL);
}

void threads::stop(void)
{
    auto nom = threads::items.size();
    while (nom)
    {
        nom--;
        pthread_cancel(threads::items[nom].pid);
    }
    threads::items.resize(0);
}

int main(void)
{
    std::cout << "Start" << std::endl;
    threads::start(test_proc, 3);
    std::cout << "Stop" << std::endl;
    return EXIT_SUCCESS;
}

#include <pthread.h>

Тебе обязательно в 2017-м году, когда уже готов финальный черновик C++17, изобретать велосипед, который был изобретен во времена C++11? Вот за это ты и страдаешь.

И ещё. Почитай man по

│pthread_cancel() │ Thread safety │ MT-Safe │
А потом - вот это http://man7.org/linux/man-pages/man7/signal-safety.7.html

asaw ★★★★★
()
Последнее исправление: asaw (всего исправлений: 1)
Ответ на: комментарий от asaw

Спасибо.

Кстати про pthread_cancel. Как остановить нить с std::thread?

Что то такое? Или лучше способ есть?

std::thread thread;
...
pthread_cancel(thread.native_handle());
...
user0xff
() автор топика
Ответ на: комментарий от user0xff

Остановить только с помощью самой нити - сделать там какую-нибуть condition_variable и устроить логику так, чтобы нить эту cv периодически проверяла. После этого делать http://en.cppreference.com/w/cpp/thread/thread/join Впрочем, с pthreads на самом деле всё обстоит примерно так же - pthread_cancel с гарантией останавливает нить только в точке отмены типа системного вызова read(), но выхода из такой функции ты можешь добиться послав сигнал вроде того же SIGINT.

asaw ★★★★★
()
Последнее исправление: asaw (всего исправлений: 2)
Ответ на: комментарий от DarkEld3r

Дык с 14ого стандарта, в 11ом лажанули немного :)

pon4ik ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.