LINUX.ORG.RU

нерпонятки с pthreads


0

0

почему-то не вызывается cleanup handler (зарегистрированый при помощи pthread_cleanup_push() в потоке, который в будущем отменят) после того как поток будет отменен при помощи pthread_cancel().

отменяемый поток при этом находится в pthread_cond_wait()

т.е есть такая картина: 1) поток A - делает pthread_cleanup_push(cleanup_handler, &some_mutex) после чего висит на pthread_cond_wait()

2) поток Б - делает pthread_cancel(&threadA)

согласно POSIX должен вызваться cleanup_handler, но этого почему-то не происходит :(

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

код такой:

#include <stdio.h>

#include <pthread.h>


pthread_cond_t cond = PTHREAD_COND_INITIALISER;

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALISER;

void cleanup_routine(void *dummy) {

printf("CLEANUP_HANDLER: called!\n");

}

void *A(void *dummy) { //thread A body

int retval = pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL)

if (0 != retval) {

printf("A: cannot enable cancellationing\n");
pthread_exit(NULL);
}
retval = pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
if (0 != retval) {
printf("A: cannot enable cancel type!\n");
pthread_exit(NULL);
}

pthread_cleanup_push(cleanup_handler, &mutex);

pthread_mutex_lock(&mutex);
pthread_cond_wait(&cond, &mutex);
pthread_mutex_unlock(&mutex);


pthread_cleanup_pop(0);
pthread_exit(NULL);
}

void *B(void *dummy) {//thread B body
sleep(5);
pritnf("B: cancellationing the thread A in progress!\n");
if (0 > pthread_cancel(&threadA)) {
printf("B: cannot cancel A\n");
}
pthread_exit(NULL);
}

int main(int argc, char **argv) {
pthread_create(&threadA, NULL, A, NULL);
pthread_create(&threadB, NULL, B, NULL);
pthread_join(&threadB, NULL);
return 0;
}

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

Я за точность не ручаюсь, но в свое время Ксавьер писал,
что блокируемые системные вызовы должны являться cancelation
points,но на текущий момент такого в ядре нет. Как с этим обстоит
дело сейчес - не знаю.

Для того, что бы у тебя код работал при любых условиях: вместо бесконечной блокировки в pthread_cond_wait поставь
pthread_cond_timedwait c указанием тайм аута и все это засунь в цикл.
Тогда работать будет везде и всегда.



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

Да, чуть не забыл. Когда выходишь из потока В после убийства потока А - поставь паузу. Отмена потока занимает некоторое время: то есть, для того что бы что-то напечаталось из обработчика завершения потока, нужно время.

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

Приведённый код не может работать по простой причине: он не скомпилируется. Возможно, в исходной программе есть такие же кунштюки типа

pthread_cancel(&threadA)

вместо

pthread_cancel(threadA).

Это будет компилироваться, но приведёт к неопределённому поведению.

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

былин спасибище вам всем огромное и вам, jek_, в особенности.

ступил просто гигантски.

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