Man page - pthread_cleanup_pop(3)

Packages contains this manual

Available languages:

en fr ja ru

Manual

pthread_cleanup_push

НАИМЕНОВАНИЕ
БИБЛИОТЕКА
ОБЗОР
ОПИСАНИЕ
ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ
ОШИБКИ
АТРИБУТЫ
ВЕРСИИ
СТАНДАРТЫ
ИСТОРИЯ
ПРИМЕРЫ
Исходный код программы
СМОТРИТЕ ТАКЖЕ
ПЕРЕВОД

НАИМЕНОВАНИЕ

pthread_cleanup_push, pthread_cleanup_pop - push and pop thread cancelation clean-up handlers

БИБЛИОТЕКА

Библиотека потоков POSIX ( libpthread , -lpthread )

ОБЗОР

#include <pthread.h>

void pthread_cleanup_push(void (* routine )(void *), void * arg );
void pthread_cleanup_pop(int
execute );

ОПИСАНИЕ

These functions manipulate the calling thread’s stack of thread-cancelation clean-up handlers. A clean-up handler is a function that is automatically executed when a thread is canceled (or in various other circumstances described below); it might, for example, unlock a mutex so that it becomes available to other threads in the process.

Функция pthread_cleanup_push () помещает обработчик routine наверх стека очищающих обработчиков. Позднее, при вызове routine , ему будет передан arg в качестве аргумента.

Функция pthread_cleanup_pop () удаляет обработчик с вершины стека очищающих обработчиков, и, возможно, выполняет его, если execute не равно нулю.

A cancelation clean-up handler is popped from the stack and executed in the following circumstances:

Когда нить отменяется, все очищающие обработчики из стека выталкиваются и вызываются в обратном порядке их помещения в стек.

Когда нить завершается вызовом pthread_exit (3), все очищающие обработчики выполняются как описано в предыдущем пункте (очищающие обработчики не вызываются, если нить завершается возвратом из начальной функции нити).

Когда нить вызывает pthread_cleanup_pop () с ненулевым значением аргумента execute , самый верхний очищающий обработчик выталкивается и выполняется.

POSIX.1 permits pthread_cleanup_push () and pthread_cleanup_pop () to be implemented as macros that expand to text containing ' { ' and ' } ', respectively. For this reason, the caller must ensure that calls to these functions are paired within the same function, and at the same lexical nesting level. (In other words, a clean-up handler is established only during the execution of a specified section of code.)

Вызов longjmp (3) ( siglongjmp (3)) приводит к непредсказуемым результатам, если был сделан любой вызов в pthread_cleanup_push () или pthread_cleanup_pop () без соответствующего вызову пары, так как буфер перехода (jump buffer) был заполнен setjmp (3) ( sigsetjmp (3)). Подобным образом, вызов longjmp (3) ( siglongjmp (3)) изнутри очищающего обработчика приводит к непредсказуемым результатам, если буфер перехода также не был заполнен setjmp (3) ( sigsetjmp (3)) внутри обработчика.

ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ

Данные функции не возвращают никаких значений.

ОШИБКИ

Эти функции не вызывают ошибок.

АТРИБУТЫ

Описание терминов данного раздела смотрите в attributes (7).

Image grohtml-611271-1.png

ВЕРСИИ

On glibc, the pthread_cleanup_push () and pthread_cleanup_pop () functions are implemented as macros that expand to text containing ' { ' and ' } ', respectively. This means that variables declared within the scope of paired calls to these functions will be visible within only that scope.

В POSIX.1 сказано, что результат использования return , break , continue или goto для преждевременного оставления блока, окружающего pthread_cleanup_push () и pthread_cleanup_pop (), не определён. В переносимых приложениях не нужно так делать.

СТАНДАРТЫ

POSIX.1-2008.

ИСТОРИЯ

POSIX.1-2001. glibc 2.0.

ПРИМЕРЫ

The program below provides a simple example of the use of the functions described in this page. The program creates a thread that executes a loop bracketed by pthread_cleanup_push () and pthread_cleanup_pop (). This loop increments a global variable, cnt , once each second. Depending on what command-line arguments are supplied, the main thread sends the other thread a cancelation request, or sets a global variable that causes the other thread to exit its loop and terminate normally (by doing a return ).

In the following shell session, the main thread sends a cancelation request to the other thread:

$ ./a.out
Запущена новая нить
cnt = 0
cnt = 1
Отменяем нить
Вызван очищающий обработчик
Нить отменена; cnt = 0

From the above, we see that the thread was canceled, and that the cancelation clean-up handler was called and it reset the value of the global variable cnt to 0.

В следующем сеансе главная программа изменяет глобальную переменную, что вызывает штатное завершение другой нити:

$ ./a.out x
Запущена новая нить
cnt = 0
cnt = 1
Нить завершилась штатным образом; cnt = 2

Здесь мы видим, что очищающий обработчик не вызывался (так как cleanup_pop_arg равно 0), и поэтому значение cnt не сброшено.

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

$ ./a.out x 1
Запущена новая нить
cnt = 0
cnt = 1
Вызван очищающий обработчик
Нить завершилась штатным образом; cnt = 0

Здесь мы видим, что хотя нить не отменена, всё же вызван очищающий обработчик, так как в pthread_cleanup_pop () передан ненулевой аргумент.

Исходный код программы

#include <errno.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#define handle_error_en(en, msg) \
do { errno = en; perror(msg); exit(EXIT_FAILURE); } while (0)
static int done = 0;
static int cleanup_pop_arg = 0;
static int cnt = 0;
static void
cleanup_handler(void *arg)
{
printf("Called clean-up handler\n");
cnt = 0;
}
static void *
thread_start(void *arg)
{
time_t curr;
printf("New thread started\n");
pthread_cleanup_push(cleanup_handler, NULL);
curr = time(NULL);
while (!done) {
pthread_testcancel(); /* A cancelation point */
if (curr < time(NULL)) {
curr = time(NULL);
printf("cnt = %d\n", cnt); /* A cancelation point */
cnt++;
}
}
pthread_cleanup_pop(cleanup_pop_arg);
return NULL;
}
int
main(int argc, char *argv[])
{
pthread_t thr;
int s;
void *res;
s = pthread_create(&thr, NULL, thread_start, NULL);
if (s != 0)
handle_error_en(s, "pthread_create");
sleep(2); /* Allow new thread to run a while */
if (argc > 1) {
if (argc > 2)
cleanup_pop_arg = atoi(argv[2]);
done = 1;
} else {
printf("Canceling thread\n");
s = pthread_cancel(thr);
if (s != 0)
handle_error_en(s, "pthread_cancel");
}
s = pthread_join(thr, &res);
if (s != 0)
handle_error_en(s, "pthread_join");
if (res == PTHREAD_CANCELED)
printf("Thread was canceled; cnt = %d\n", cnt);
else
printf("Thread terminated normally; cnt = %d\n", cnt);
exit(EXIT_SUCCESS);
}

СМОТРИТЕ ТАКЖЕ

pthread_cancel (3), pthread_cleanup_push_defer_np (3), pthread_setcancelstate (3), pthread_testcancel (3), pthreads (7)

ПЕРЕВОД

Русский перевод этой страницы руководства разработал(и) Alexey, Azamat Hackimov <azamat.hackimov@gmail.com>, kogamatranslator49 <r.podarov@yandex.ru>, Darima Kogan <silverdk99@gmail.com>, Max Is <ismax799@gmail.com>, Yuri Kozlov <yuray@komyakino.ru>, Иван Павлов <pavia00@gmail.com> и Kirill Rekhov <krekhov.dev@gmail.com>

Этот перевод является свободной программной документацией; он распространяется на условиях общедоступной лицензии GNU (GNU General Public License - GPL, https://www.gnu.org/licenses/gpl-3.0.html версии 3 или более поздней) в отношении авторского права, но БЕЗ КАКИХ-ЛИБО ГАРАНТИЙ.

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