LINUX.ORG.RU

Завершение потока через pthread_cancel()


0

0

Друзья, столкнулся с проблемкой когда из главного потока нужно завершить один из порожденных. Рабочая функция порожденного потока следующая:

void* work( void* var ) { while( true ) {

pthread_testcancel();

read_data_from_file();

pthread_testcancel();

sleep( 4 ); } }

В главном потоке делаю следующее

pthread_cancel( thread_id );

pthread_join();

... и не как не могу дождаться завершения дочернего потока. При исследовании стека в gdb, видно что дочерний поток так и не вышел из sleep. Кто-нибудь знает, в чет тут может быть дело?


Ответ на: комментарий от tailgunner

Да, просто висит и всё... Я с консоли процесс прибиваю через kill, соответственно вижу отладку о том что все потоки завершились корректно, кроме одного из порожденных. Мне надоедает ждать, я нажимаю на Enter и получаю сообщение Aborted в консоль.

За ссылку спасибо.

snoopy
() автор топика
Ответ на: комментарий от snoopy

> Да, просто висит и всё...

Очень странно. sleep должен завершиться, и после этого должны одна за другой завершиться обе нити. Какая версия libc? Ядро? И как насчет аргументов в pthread_join?

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

Ну то есть pthread_join() никак не дождется завершения требуемого потока. pthread_join получает необходимые аргументы - id треда и ссылку на переменную статуса. Версия libc - 2.3.4, ядро - 2.6.9-11.ELsmp.

snoopy
() автор топика
Ответ на: комментарий от snoopy

lklk

По-моему вам нужно:

1)pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL)в потоке который Вы хотите отменять

2) Убрать pthread_testcancel() нафик 3) Убедиться что sleep() является cancellation point. 4) Немножко почитать про POSIX threads

С уважением, йуная@кошечга.

int_0dh
()
Ответ на: lklk от int_0dh

> 1)pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL)в потоке который Вы хотите отменять

/me думал, что канселлябильность включена по умолчанию. Если нет, то это могло бы всё объяснить.

tailgunner ★★★★★
()
Ответ на: комментарий от snoopy

> Я делаю и pthread_setcancelstate( PTHREAD_CANCEL_ENABLE ) и pthread_setcanceltype( PTHREAD_CANCEL_DEFERRED ). Вот.

Тогда тебе осталось запостить сюда минимизированный компилябельный вариант проблемной проги :)

tailgunner ★★★★★
()

У меня, кстати, та же проблема - не могу дождаться завершения потока.
Делал по-деревенски (заранее прошу прощения у эстетов):
   pthread_cancel(thread);
   while(!(thread_param.dead))
      usleep(1000);
   <exit>
И программа висла. Но вот если от него отстать, т.е.
   pthread_cancel(thread);
   <exit>
,то процесс завершается. А вот ещё пример: есть некий поток, работающий в фоновом режиме.
   void * some_thread_f(void *arg){
      bool *flag = (bool *)arg;
      while(true){
         if(*flag){
            doSomeAction();
            *flag=false;
         }
         doOtherActions();
      }
   }
А есть обработчик нажатия кнопки (GTK+), который должен заставить фоновый поток вызвать функцию doSomeAction() и дождаться окончания вызова:
   void * button_press_callback(int ar, void * arg){
      bool *flag = (bool *)arg;
      *flag = true;
      while(*flag)
         usleep(1000);
   }
Так вот по нажатию кнопки программа навсегда уходит в себя.
Решил проблему просто - содержимое button_press_callback поместил в тело потока, а обработчиком запускаю этот поток. Заработало.
От этого у меня возникло ощущение, что потоки не могут нормально конкурировать с обработчиками событий, функцией main и т.п.

philip
()
Ответ на: комментарий от tailgunner

Большое спасибо всем, кто откликнулся. Я отказался от использования POSIX-функций аннулирования потоков. Теперь просто проверяю свои флаги, и когда необходимо - выхожу из рабочей функции потока. Так усё работает. Если честно, так и не понял, либо я что-то не учёл, либо libpthread. Запостить минимизированный компиллябельный вариант не смогу - быстро не получится. Но там простой подход типа pthread_cancel() - pthread_join().

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