Как точно выпустить pthreads rwlock после pthread_cancel? - PullRequest
1 голос
/ 10 ноября 2010

Рассмотрим следующий поток программы:

pthread_rwlock_rdlock( &mylock);
... compute a lot, maybe be the target of a pthread_cancel() ...
pthread_rwlock_unlock( &mylock);

, который собирается оставить блокировку в состоянии rdlock, если поток отменен.

Похоже, что "правильное", что нужно сделать, это использовать pthread_cleanup_push () и pthread_cleanup_pop () и выполнить разблокировку внутри моей функции очистки, но, похоже, нет правильного порядка для вызовов функции:

void my_cleanup(void *arg) { pthread_rwlock_unlock(&mylock); }
...
pthread_cleanup_push( my_cleanup, 0);
/* A */
pthread_rwlock_rdlock( &mylock);
... compute a lot, maybe be the target of a pthread_cancel() ...
pthread_cleanup_pop( 1);

... это выглядит почти правильно, за исключением того, что если pthread_cancel () попадет в "A", очистка разблокирует mylock, который еще не заблокирован, что приводит к неопределенному поведению.

Полный ответ может быть следующим:

void my_cleanup(void *arg) { pthread_rwlock_unlock(&mylock); }
...

pthread_setcancelstate( PTHREAD_CANCEL_DISABLE, &oldstate);
pthread_cleanup_push( my_cleanup, 0);
pthread_rwlock_rdlock( &mylock);
pthread_setcancelstate( oldstate, 0);
... compute a lot, maybe be the target of a pthread_cancel() ...
pthread_cleanup_pop( 1);

, но в этот момент мне кажется, что я оборачиваю некоторые хорошо определенные примитивы в бинты.

Так что есть ли лучшеидиома для этого?

Ответы [ 2 ]

2 голосов
/ 21 января 2011

Если вы не разрешите асинхронную отмену, ожидающая pthread_cancel () будет обрабатываться только в известных точках.Поэтому следует безопасно нажимать сразу после успешной блокировки, а щелчок - перед разблокировкой.

0 голосов
/ 11 ноября 2010

Я взглянул на источник glibc / nptl и не вижу лучшего способа, чем вы предлагали. В рулоке нет даже состояния, достаточного для того, чтобы вы "обманули" и поверили, что сторона разблокировки узнает, получена ли у вас блокировка или нет. Если вы не получили блокировку, но кто-то другой сделал, ложная разблокировка повредит состояние (а не вернет ошибку).

На самом деле, я не могу найти причину, по которой удачно расположенный SIGCANCEL не смог прервать сам pthread_rwlock_rdlock и оставить блокировку lll_lock (внутреннюю glibc внутреннюю) заблокированной, что привело к зависанию всех других доступов к rwlock. Так что ваш PTHREAD_CANCEL_DISABLE может быть еще важнее. Также добавьте один вокруг очистки, если вы действительно планируете создавать / отменять многие из этих тем. Для стресс-теста стоило бы написать тестовую программу.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...