Убить поток C++ 11
От: dosik Россия www.dosik.ru
Дата: 06.04.16 14:16
Оценка:
Так уж получилось, что поставили мне библиотечку, которая работает только в блокирующем режиме, что то типа
resulttype result = waitsomуevent(params ...);

и ни как иначе, ни таймаутов, ни мултиплексора, ни чего другого. Пока с этим надо как-то жить.
Раздал я каждому такому "событию" по зацикленному потоку, фьючерсами забираю результат (там хоть таймауты на ожидание есть).
Но вот когда необходимо завершить программу, возникает проблема с блокировкой при присоединения потока:
if (somethread.joinable())
    somethread.join()   // <--- Вот тут блокирует

чего в общем то и следовало ожидать. По симу единственным решением вижу уничтожение потока грубой силой. Но вот что-то не могу найти как, хотя где-то помниться читал, что вроде как возможно.
И дополню: сгенерит событие самому, заменить библиотеку нельзя. Такое ТЗ.
Re: Убить поток C++ 11
От: uzhas Ниоткуда  
Дата: 06.04.16 14:43
Оценка:
Здравствуйте, dosik, Вы писали:

D>Раздал я каждому такому "событию" по зацикленному потоку, фьючерсами забираю результат (там хоть таймауты на ожидание есть).

я тут плохо понял каким образом потоки раздаются и как фьючерсы используются, но нельзя ли потоку при создании передать нечто (хоть ссылку на булевый флаг, хоть ивент), за что можно дернуть при завершении, чтобы потоки вышли бы без терминации?

D>По симу единственным решением вижу уничтожение потока грубой силой.

это очень плохая практика, но тем не менее подскажу: надо использовать thread::native_handle : http://en.cppreference.com/w/cpp/thread/thread/native_handle и платформозависимые функции
первая ссылка из гугла: http://stackoverflow.com/questions/12207684/how-do-i-terminate-a-thread-in-c11
но я, кстати, слышал от умных людей. что все же хотят добавить этот метод в std::thread. видимо, пока в комитете копья ломают
Re: Убить поток C++ 11
От: Erop Россия  
Дата: 06.04.16 15:01
Оценка:
Здравствуйте, dosik, Вы писали:

D>чего в общем то и следовало ожидать. По симу единственным решением вижу уничтожение потока грубой силой. Но вот что-то не могу найти как, хотя где-то помниться читал, что вроде как возможно.

D>И дополню: сгенерит событие самому, заменить библиотеку нельзя. Такое ТЗ.

А ОС какая? А то всякие ОС, вроде винды не готовы к убийству потока, когда он в ядре...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[2]: Убить поток C++ 11
От: dosik Россия www.dosik.ru
Дата: 06.04.16 15:02
Оценка:
Здравствуйте, uzhas, Вы писали:

U>Здравствуйте, dosik, Вы писали:


U>я тут плохо понял каким образом потоки раздаются и как фьючерсы используются, но нельзя ли потоку при создании передать нечто (хоть ссылку на булевый флаг, хоть ивент), за что можно дернуть при завершении, чтобы потоки вышли бы без терминации?


Про фьючерсы — в карту складываются ожидаемые события по связке: id события — обещание (promise). Карта заполняется основным потоком. Как только "ловится" событие с этим id, в соответствующее обещание записывается значение, что и генерит фьючерс. Вот такие вот кастыли, чтобы создать некую асинхронность на базе блокирующей функции.
А потоки именно так и крутяться:
std::atomic<bool> iswork;
...
void threadfunc(){
    while (iswork.load()){
    ...
        resulttype result = waitsomeevent(params ...);
    ...
    }
}

И как только "пора заканчивать", iswork устанавливается в false. Только что толку, если цикл блокируется в waitsomeevent?
И как я уже сказал, самому сгенерит событие нельзя.

U>это очень плохая практика

Для начала — это очень плохая библиотека. Но обещают доработать.
А так конечно согласен, но думаю наверху проблему описал более подробно.
Re[2]: Убить поток C++ 11
От: dosik Россия www.dosik.ru
Дата: 06.04.16 15:03
Оценка:
Здравствуйте, Erop, Вы писали:

E>А ОС какая? А то всякие ОС, вроде винды не готовы к убийству потока, когда он в ядре...

Linux (Ubuntu, Debian).
Re[2]: Убить поток C++ 11
От: ononim  
Дата: 06.04.16 15:39
Оценка:
D>>чего в общем то и следовало ожидать. По симу единственным решением вижу уничтожение потока грубой силой. Но вот что-то не могу найти как, хотя где-то помниться читал, что вроде как возможно.
D>>И дополню: сгенерит событие самому, заменить библиотеку нельзя. Такое ТЗ.
E>А ОС какая? А то всякие ОС, вроде винды не готовы к убийству потока, когда он в ядре...
С чего это вдруг? Не ну конечно корявый драйвер может и взбрыкнуть, а скорей всего — просто не среагировать на киляние потока, но в основном все нормально с этим и в винде.
Как много веселых ребят, и все делают велосипед...
Re: Убить поток C++ 11
От: ononim  
Дата: 06.04.16 15:43
Оценка:
Лучше убить процесс. Раз уж проблема только с завершением. Посохранял все что нужно, и в exit(0). Или exit тоже виснет?
Как много веселых ребят, и все делают велосипед...
Re: Убить поток C++ 11
От: andyp  
Дата: 06.04.16 15:47
Оценка:
Здравствуйте, dosik, Вы писали:

D>Но вот когда необходимо завершить программу, возникает проблема с блокировкой при присоединения потока:

D>
D>if (somethread.joinable())
D>    somethread.join()   // <--- Вот тут блокирует
D>

D>чего в общем то и следовало ожидать. По симу единственным решением вижу уничтожение потока грубой силой. Но вот что-то не могу найти как, хотя где-то помниться читал, что вроде как возможно.
D>И дополню: сгенерит событие самому, заменить библиотеку нельзя. Такое ТЗ.

Почему бы просто не вызвать detach()? ОС приберет за тобой при завершении программы.
Re[2]: Убить поток C++ 11
От: dosik Россия www.dosik.ru
Дата: 06.04.16 15:55
Оценка:
Здравствуйте, andyp, Вы писали:

A>Почему бы просто не вызвать detach()? ОС приберет за тобой при завершении программы.


По тому, что он все еще "жив и ждет события", и если я снова запущу другой экземпляр класса, который снова будет "ждать события", то есть вариант, что при возникновении события его перехватит еще пока "живущий" поток старый поток, и "событие" пропадет.
В случае, если остановка потока есть выход из программы — это подходит, в случае возникновения вероятности перезапуска — нет.
Re[3]: Убить поток C++ 11
От: andyp  
Дата: 06.04.16 16:01
Оценка:
Здравствуйте, dosik, Вы писали:

D>По тому, что он все еще "жив и ждет события", и если я снова запущу другой экземпляр класса, который снова будет "ждать события", то есть вариант, что при возникновении события его перехватит еще пока "живущий" поток старый поток, и "событие" пропадет.

D>В случае, если остановка потока есть выход из программы — это подходит, в случае возникновения вероятности перезапуска — нет.

Разумеется. Я только случай завершения программы имел в виду. Понял так, что завершиться нормально не можешь.
Re[4]: Убить поток C++ 11
От: dosik Россия www.dosik.ru
Дата: 06.04.16 16:05
Оценка:
Здравствуйте, andyp, Вы писали:

A>Разумеется. Я только случай завершения программы имел в виду. Понял так, что завершиться нормально не можешь.

Да я так сам думал, пока не переиграли тут )))
Re[2]: Убить поток C++ 11
От: dosik Россия www.dosik.ru
Дата: 06.04.16 16:05
Оценка:
Здравствуйте, ononim, Вы писали:

O>Лучше убить процесс. Раз уж проблема только с завершением. Посохранял все что нужно, и в exit(0). Или exit тоже виснет?

Нет, exit не виснет, но как оказалось нужно нормальное завершение.
Re[3]: Убить поток C++ 11
От: dosik Россия www.dosik.ru
Дата: 06.04.16 16:10
Оценка:
Здравствуйте, ononim, Вы писали:

O>С чего это вдруг? Не ну конечно корявый драйвер может и взбрыкнуть, а скорей всего — просто не среагировать на киляние потока, но в основном все нормально с этим и в винде.

Ну вот на Linux например после:
    if (my_reader_thread.joinable()) {
        pthread_t t = my_reader_thread.native_handle();
        pthread_cancel(t);
    }

Получаю: FATAL: exception not rethrown
Или чет не то вызвал я?
Re[3]: Убить поток C++ 11
От: ononim  
Дата: 06.04.16 16:31
Оценка: +3
O>>Лучше убить процесс. Раз уж проблема только с завершением. Посохранял все что нужно, и в exit(0). Или exit тоже виснет?
D>Нет, exit не виснет, но как оказалось нужно нормальное завершение.
"нужно нормальное завершение" и "нужно убить поток системными средствами" — это взаимоисключающие положения. Выбрать можно только одно. Убивание процесса целиком — это и то компромиссное решение, лишь минимизирующее риск проблем.
Как много веселых ребят, и все делают велосипед...
Re[4]: Убить поток C++ 11
От: uzhas Ниоткуда  
Дата: 06.04.16 16:38
Оценка:
Здравствуйте, dosik, Вы писали:

D>Получаю: FATAL: exception not rethrown

D>Или чет не то вызвал я?
судя по гуглу, нужно использовать конструкцию
        try {
            function_(); <--- вот здесь надо вызывать стороннюю библиотеку
        }
        catch (abi::__forced_unwind&) {
            throw;
        }
        catch (...) {}

в том потоке, который будет кенселиться
линк: http://stackoverflow.com/questions/20647365/handling-pthread-cancellation-points-in-c-destructors-when-unwinding-due-to-an
Re[4]: Убить поток C++ 11
От: dosik Россия www.dosik.ru
Дата: 06.04.16 17:07
Оценка:
Здравствуйте, ononim, Вы писали:

O>"нужно нормальное завершение" и "нужно убить поток системными средствами" — это взаимоисключающие положения. Выбрать можно только одно. Убивание процесса целиком — это и то компромиссное решение, лишь минимизирующее риск проблем.


Ну значит, если не найду приемлемого решения, будет у класса, юзающего "недоделку" только метод start(), а метод stop() до лучших времен, ну или так и задокументировать, что мол остановить потоки можно только завершением процесса. Документированный баг — не баг, а фича )))
Re[5]: Убить поток C++ 11
От: dosik Россия www.dosik.ru
Дата: 06.04.16 17:17
Оценка:
Здравствуйте, uzhas, Вы писали:

U>линк: http://stackoverflow.com/questions/20647365/handling-pthread-cancellation-points-in-c-destructors-when-unwinding-due-to-an


Ноль эмоций. остановлюсь пока не деатаче и выходе из процесса, там посмотрим )))
Спасибо.
Re[4]: Убить поток C++ 11
От: Erop Россия  
Дата: 06.04.16 17:20
Оценка: 18 (2) +2
Здравствуйте, ononim, Вы писали:

O>"нужно нормальное завершение" и "нужно убить поток системными средствами" — это взаимоисключающие положения. Выбрать можно только одно. Убивание процесса целиком — это и то компромиссное решение, лишь минимизирующее риск проблем.


Ещё можно блокирующую библиотеку в другой процесс форкнуть, и его потом убивать, а синхронизироваться по rpc, например...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[5]: Убить поток C++ 11
От: dosik Россия www.dosik.ru
Дата: 06.04.16 17:27
Оценка:
Здравствуйте, Erop, Вы писали:

E>Ещё можно блокирующую библиотеку в другой процесс форкнуть, и его потом убивать, а синхронизироваться по rpc, например...


Можно, ну это уж слишком лихо для временных решений )))
Re[6]: Убить поток C++ 11
От: Erop Россия  
Дата: 06.04.16 18:08
Оценка:
Здравствуйте, dosik, Вы писали:

D>Можно, ну это уж слишком лихо для временных решений )))


Ну вынести говнобиблиотеку в другой процесс, не факт, что плохое решение...
Эту дыру они может и заткнут, но вдруг это не последняя ошибка?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.