- bullseye-backports 4.18.1-1~bpo11+1
PTHREAD_MUTEXATTR_SETROBUST(3) | Руководство программиста Linux | PTHREAD_MUTEXATTR_SETROBUST(3) |
ИМЯ¶
pthread_mutexattr_getrobust, pthread_mutexattr_setrobust - возвращает и изменяет атрибут устойчивости в объекте мьютексных атрибутов
СИНТАКСИС¶
#include <pthread.h>
int pthread_mutexattr_getrobust(const pthread_mutexattr_t *attr, int *robustness); int pthread_mutexattr_setrobust(const pthread_mutexattr_t *attr, int robustness);
Компилируется и компонуется вместе с -pthread.
pthread_mutexattr_getrobust(),
pthread_mutexattr_setrobust():
ОПИСАНИЕ¶
Функция pthread_mutexattr_getrobust() помещает значение атрибута устойчивости (robustness) из объекта мьютексных атрибутов, на который указывает attr, в *robustness. Функция pthread_mutexattr_setrobust() изменяет значение атрибута устойчивости в объекте мьютексных атрибутов, на который указывает attr, на значение, заданное в *robustness.
Атрибут устойчивости определяет поведение мьютекса после того как владеющая нить завершает работу, но не разблокировала мьютекс. Для robustness возможны следующие значения:
- PTHREAD_MUTEX_STALLED
- Значение по умолчанию для объекта мьютексных атрибутов. Если мьютекс инициализирован с атрибутом PTHREAD_MUTEX_STALLED и его владелец завершает работу без его разблокировки, то после этого мьютекс остаётся заблокированным и все последующие попытки вызова pthread_mutex_lock(3) для этого мьютекса будут заблокированы навсегда.
- PTHREAD_MUTEX_ROBUST
- Если мьютекса инициализирован с атрибутом PTHREAD_MUTEX_ROBUST и и его владелец завершает работу без его разблокировки,то все последующие попытки вызова pthread_mutex_lock(3) для этого мьютекса будут успешно выполнены возвращается EOWNERDEAD, чтобы показать, что первоначальный владелец не существует и мьютекс находится в неопределенном состоянии. Обычно, после возврата EOWNERDEAD перед началом использования следующий владелец должен вызвать pthread_mutex_consistent(3) над полученным мьютексом, чтобы снова сделать его согласованным.
- Если следующий владелец разблокирует мьютекс с помощью pthread_mutex_unlock(3) до того, как сделать его согласованным, мьютекс станет необратимо неработоспособен и последующие попытки заблокировать его с помощью pthread_mutex_lock(3) будут завершаться ошибкой ENOTRECOVERABLE. Для такого мьютекса доступна только одна операция — pthread_mutex_destroy(3).
- Если следующий владелец завершит работу до вызова pthread_mutex_consistent(3), то последующие операций pthread_mutex_lock(3) с этим мьютексом будут по прежнему возвращать EOWNERDEAD.
Заметим, что аргумент attr у pthread_mutexattr_getrobust() и pthread_mutexattr_setrobust() должен указывать на объект мьютексных атрибутов, который был инициализирован pthread_mutexattr_init(3), в противном случае поведение не определено.
ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ¶
При успешном выполнении эти функции возвращают 0. При ошибке возвращается положительный номер ошибки.
В реализации glibc функция pthread_mutexattr_getrobust() всегда возвращает ноль.
ОШИБКИ¶
- EINVAL
- Помимо PTHREAD_MUTEX_STALLED или PTHREAD_MUTEX_ROBUST в pthread_mutexattr_setrobust() передано что-то ещё.
ВЕРСИИ¶
Функции pthread_mutexattr_getrobust() и pthread_mutexattr_setrobust() добавлены в glibc версии 2.12.
СООТВЕТСТВИЕ СТАНДАРТАМ¶
POSIX.1-2008.
ЗАМЕЧАНИЯ¶
В реализации Linux при использовании общих для процессов устойчивых мьютексов ожидающая нить также получает уведомление EOWNERDEAD, если владелец устойчивого мьютекса выполняет execve(2) без предварительной разблокировки мьютекса. В POSIX.1 не указана данная подробность, но такое же поведение также встречается и в нескольких других реализациях.
До появления pthread_mutexattr_getrobust() и pthread_mutexattr_setrobust() в POSIX, в glibc определись следующие эквиваленты нестандартных функций, если определён _GNU_SOURCE:
int pthread_mutexattr_getrobust_np(const pthread_mutexattr_t *attr, int *robustness); int pthread_mutexattr_setrobust_np(const pthread_mutexattr_t *attr, int robustness);
Соответственно, также определены константы PTHREAD_MUTEX_STALLED_NP и PTHREAD_MUTEX_ROBUST_NP.
Данный имеющийся только в GNU программный интерфейс, впервые появившийся в glibc 2.4, в настоящее время устарел и не должен использоваться в новых программах.
ПРИМЕРЫ¶
В программе, представленной далее, показывается использование атрибута устойчивости в объекте мьютексных атрибутов. В этой программе нить, удерживающая мьютекс, завершает работу без разблокировки мьютекса. После этого главная нить захватывает мьютекс и получает ошибку EOWNERDEAD, после чего делает мьютекс согласованным.
Пример сеанса работы с программой:
$ ./a.out [original owner] Setting lock... [original owner] Locked. Now exiting without unlocking. [main] Attempting to lock the robust mutex. [main] pthread_mutex_lock() returned EOWNERDEAD [main] Now make the mutex consistent [main] Mutex is now consistent; unlocking
Исходный код программы¶
#include <stdlib.h> #include <stdio.h> #include <unistd.h> #include <pthread.h> #include <errno.h> #define handle_error_en(en, msg) \
do { errno = en; perror(msg); exit(EXIT_FAILURE); } while (0) static pthread_mutex_t mtx; static void * original_owner_thread(void *ptr) {
printf("[первый владелец] Установка блокировки…\n");
pthread_mutex_lock(&mtx);
printf("[original owner] Готово. Теперь выходим без разблокировки.\n");
pthread_exit(NULL); } int main(int argc, char *argv[]) {
pthread_t thr;
pthread_mutexattr_t attr;
int s;
pthread_mutexattr_init(&attr);
/* инициализируем объект атрибутов */
pthread_mutexattr_setrobust(&attr, PTHREAD_MUTEX_ROBUST);
/* задаём устойчивость */
pthread_mutex_init(&mtx, &attr); /* инициализируем мьютекс */
pthread_create(&thr, NULL, original_owner_thread, NULL);
sleep(2);
/* «нить_первый_владелец» к этому моменту должна завершиться */
printf("[main] Attempting to lock the robust mutex.\n");
s = pthread_mutex_lock(&mtx);
if (s == EOWNERDEAD) {
printf("[main] pthread_mutex_lock() returned EOWNERDEAD\n");
printf("[main] Now make the mutex consistent\n");
s = pthread_mutex_consistent(&mtx);
if (s != 0)
handle_error_en(s, "pthread_mutex_consistent");
printf("[main] Mutex is now consistent; unlocking\n");
s = pthread_mutex_unlock(&mtx);
if (s != 0)
handle_error_en(s, "pthread_mutex_unlock");
exit(EXIT_SUCCESS);
} else if (s == 0) {
printf("[main] pthread_mutex_lock() unexpectedly succeeded\n");
exit(EXIT_FAILURE);
} else {
printf("[main] pthread_mutex_lock() unexpectedly failed\n");
handle_error_en(s, "pthread_mutex_lock");
} }
СМ. ТАКЖЕ¶
get_robust_list(2), set_robust_list(2), pthread_mutex_consistent(3), pthread_mutex_init(3), pthread_mutex_lock(3), pthreads(7)
ЗАМЕЧАНИЯ¶
Эта страница является частью проекта Linux man-pages версии 5.10. Описание проекта, информацию об ошибках и последнюю версию этой страницы можно найти по адресу https://www.kernel.org/doc/man-pages/.
ПЕРЕВОД¶
Русский перевод этой страницы руководства был сделан Alexey, Azamat Hackimov <azamat.hackimov@gmail.com>, kogamatranslator49 <r.podarov@yandex.ru>, Kogan, Max Is <ismax799@gmail.com>, Yuri Kozlov <yuray@komyakino.ru> и Иван Павлов <pavia00@gmail.com>
Этот перевод является бесплатной документацией; прочитайте Стандартную общественную лицензию GNU версии 3 или более позднюю, чтобы узнать об условиях авторского права. Мы не несем НИКАКОЙ ОТВЕТСТВЕННОСТИ.
Если вы обнаружите ошибки в переводе этой страницы руководства, пожалуйста, отправьте электронное письмо на man-pages-ru-talks@lists.sourceforge.net.
9 июня 2020 г. | Linux |