名 前
pthread_cleanup_push, pthread_cleanup_pop − ス レ ッ ド の キ ャ ン セ ル ク リ ー ン ア ッ プ ハ ン ド ラ ー の push/pop を 行 う
書 式
#include <pthread.h>
void
pthread_cleanup_push(void (*routine)(void *),
void *arg);
void pthread_cleanup_pop(int execute);
−pthread で コ ン パ イ ル し て リ ン ク す る 。
説 明
こ れ ら の 関 数 は 、 呼 び 出 し た ス レ ッ ド の ス レ ッ ド キ ャ ン セ ル 時 の ク リ ー ン ア ッ プ ハ ン ド ラ ー の ス タ ッ ク の 操 作 を 行 う 。 ク リ ー ン ア ッ プ ハ ン ド ラ ー は 、 ス レ ッ ド が キ ャ ン セ ル さ れ た 場 合 (や 以 下 で 説 明 す る 他 の 種 々 の 状 況 に お い て ) 自 動 的 に 実 行 さ れ る 関 数 で あ る 。 例 え ば 、 mutex の ロ ッ ク 解 除 を 行 い 、 プ ロ セ ス 内 の 他 の ス レ ッ ド が 利 用 で き る よ う に す る 関 数 な ど が 考 え ら れ る 。
pthread_cleanup_push() 関 数 は 、 routine を ク リ ー ン ア ッ プ ハ ン ド ラ ー の ス タ ッ ク の 一 番 上 に プ ッ シ ュ す る 。 routine が 後 で 起 動 さ れ る 際 に は 、 arg が 関 数 の 引 き 数 と 渡 さ れ る 。
pthread_cleanup_pop() 関 数 は 、 ク リ ー ン ア ッ プ ハ ン ド ラ ー の ス タ ッ ク の 一 番 上 の ル ー チ ン を 削 除 す る 。 execute が 0 以 外 の 場 合 に は そ の ル ー チ ン を 追 加 で 実 行 す る 。 キ ャ ン セ ル ク リ ー ン ア ッ プ ハ ン ド ラ ー は 、 以 下 に 示 す 場 合 に ス タ ッ ク か ら 取 り 出 さ れ 実 行 さ れ る 。
1. ス レ ッ ド が キ ャ ン セ ル さ れ た 際 に 、 ス タ ッ ク に 登 録 さ れ た 全 て の ク リ ー ン ア ッ プ ハ ン ド ラ ー が 取 り 出 さ れ て 、 実 行 さ れ る 。 ク リ ー ン ア ッ プ ハ ン ド ラ ー の 実 行 は 、 ス タ ッ ク に 登 録 さ れ た の と 逆 の 順 序 で 行 わ れ る 。 | |
2. ス レ ッ ド が |
pthread_exit(3) を 呼 び 出 し て 終 了 す る 際 に 、 全 て の ク リ ー ン ア ッ プ ハ ン ド ラ ー が 上 の 項 目 で 述 べ た の と 同 様 に 実 行 さ れ る 。 (ス レ ッ ド が ス レ ッ ド 開 始 関 数 か ら の return の 実 行 に よ り 終 了 す る 場 合 に は 、 ク リ ー ン ア ッ プ ハ ン ド ラ ー は 呼 び 出 さ れ な い 。 )
3. ス レ ッ ド が |
0 以 外 の execute 引 き 数 で pthread_cleanup_pop() を 呼 び 出 |
し た 際 に 、 ス タ ッ ク の 一 番 上 の ク リ ー ン ア ッ プ ハ ン ド ラ ー が 取 り 出 さ れ て 実 行 さ れ る 。
POSIX.1 で は 、 pthread_cleanup_push() と pthread_cleanup_pop() を そ れ ぞ れ '{' と '}' を 含 む テ キ ス ト に 展 開 す る マ ク ロ と し て 実 装 す る こ と を 許 容 し て い る 。 こ の た め 、 呼 び 出 し 側 で は 、 こ れ ら の 関 数 の 呼 び 出 し が 同 じ 関 数 の 中 で 対 と な り 、 か つ 文 法 的 に 同 じ ネ ス ト レ ベ ル (nesting level) に な る こ と を 保 証 し な け れ ば な ら な い 。 (言 い 換 え る と 、 ク リ ー ン ア ッ プ ハ ン ド ラ ー は 、 コ ー ド の 特 定 の セ ク シ ョ ン の 実 行 の 中 で の み 設 定 す る も の で あ る と 言 え る 。 )
longjmp(3) (siglongjmp(3)) の 呼 び 出 し は 、 pthread_cleanup_push() や pthread_cleanup_pop() の 呼 び 出 し が 対 と な る 呼 び 出 し が な い 状 態 で 行 わ れ た 場 合 に は 、 ど の よ う な 結 果 に な る か は 不 定 で あ る 。 こ れ は jump バ ッ フ ァ ー は setjmp(3) (sigsetjmp(3)) に よ り 設 定 さ れ る か ら で あ る 。 同 様 に 、 ク リ ー ン ア ッ プ ハ ン ド ラ ー 内 か ら の longjmp(3) (siglongjmp(3)) の 呼 び 出 し も 、 jump バ ッ フ ァ ー が ハ ン ド ラ ー 内 で setjmp(3) (sigsetjmp(3)) で 設 定 さ れ て い な い 限 り 、 ど の よ う な 結 果 に な る か は 不 定 で あ る 。
返 り 値
こ れ ら の 関 数 は 値 を 返 さ な い 。
エ ラ ー
エ ラ ー は な い 。
準 拠
POSIX.1−2001.
注 意
Linux で は 、 関 数 pthread_cleanup_push() と pthread_cleanup_pop() は 、 そ れ ぞ れ '{' と '}' を 含 む テ キ ス ト に 展 開 す る マ ク ロ と し て 実 装 さ れ て い る 。 こ の こ と は 、 こ れ ら の 関 数 を 対 で 呼 び 出 し た ス コ ー プ 内 で 宣 言 さ れ た 変 数 は 、 そ の ス コ ー プ の 中 で し か 参 照 で き な い と い う こ と を 意 味 し て い る 。
POSIX.1 に は 、 括 弧 を 含 む pthread_cleanup_push() と pthread_cleanup_pop() の ブ ロ ッ ク を そ の ま ま に し た ま ま で 、 return, break, continue, goto を 使 っ た 場 合 の 影 響 は 不 定 で あ る と 書 か れ て い る 。 移 植 性 が 必 要 な ア プ リ ケ ー シ ョ ン で は こ れ を 行 う の は 避 け る べ き で あ る 。
例
以 下 の プ ロ グ ラ ム は 、 こ の ペ ー ジ で 説 明 し た 関 数 の 簡 単 な 使 用 例 を 示 す も の で あ る 。 こ の プ ロ グ ラ ム は pthread_cleanup_push() と pthread_cleanup_pop() で 囲 ま れ た ル ー プ を 実 行 す る ス レ ッ ド を 作 成 す る 。 こ の ル ー プ で は グ ロ ー バ ル 変 数 cnt を 1 秒 に 1 ず つ 増 や し て い く 。 指 定 さ れ た コ マ ン ド ラ イ ン 引 き 数 の 内 容 に 基 づ い て 、 メ イ ン ス レ ッ ド は も う 一 つ の ス レ ッ ド に キ ャ ン セ ル 要 求 を 送 っ た り 、 も う 一 つ の ス レ ッ ド が ル ー プ を 抜 け て (return を 呼 び 出 し て ) 正 常 終 了 す る よ う に グ ロ ー バ ル 変 数 を 設 定 し た り す る 。 以 下 の シ ェ ル セ ッ シ ョ ン で は 、 メ イ ン ス レ ッ ド は も う 一 つ の ス レ ッ ド に キ ャ ン セ ル 要 求 を 送 信 す る 。
$
./a.out
New thread started
cnt = 0
cnt = 1
Canceling thread
Called clean−up handler
Thread was canceled; cnt = 0 上 記 の
実 行 例 か ら 、
ス レ ッ ド が キ
ャ ン セ ル さ れ
、 キ ャ ン セ ル
ク リ ー ン ア ッ
プ ハ ン ド ラ ー
が 呼 び 出 さ れ
、 グ ロ ー バ ル
変 数 cnt の 値 が 0
に リ セ ッ ト さ
れ て い る こ と
が 確 認 で き る
。 次 の 実 行 例
で は 、 メ イ ン
プ ロ グ ラ ム は
グ ロ ー バ ル 変
数 を 設 定 し て
、 も う 一 つ の
ス レ ッ ド が 正
常 終 了 す る よ
う に し て い る
。
$ ./a.out
x
New thread started
cnt = 0
cnt = 1
Thread terminated normally; cnt = 2 上 記
で は 、 (cleanup_pop_arg が
0 な の で ) ク リ ー
ン ア ッ プ ハ ン
ド ラ ー は 実 行
さ れ て お ら ず
、 そ の 結 果 cnt
の 値 は リ セ ッ
ト さ れ て い な
い こ と が 分 か
る 。 次 の 実 行
例 で は 、 メ イ
ン プ ロ グ ラ ム
は グ ロ ー バ ル
変 数 を 設 定 し
て 、 も う 一 つ
の ス レ ッ ド が
正 常 終 了 す る
よ う に し 、 さ
ら に cleanup_pop_arg に 0 以
外 の 値 を 渡 し
て い る 。
$ ./a.out x
1
New thread started
cnt = 0
cnt = 1
Called clean−up handler
Thread terminated normally; cnt = 0 上 記
で は 、 ス レ ッ
ド は キ ャ ン セ
ル さ れ て い な
い が 、 ク リ ー
ン ア ッ プ ハ ン
ド ラ ー が 実 行
さ れ て い な い
こ と が 分 か る
。 こ れ は
pthread_cleanup_pop() の 引 き
数 に 0 以 外 を 渡
し た か ら で あ
る 。 プ ロ グ ラ
ム の ソ ー ス
#include <pthread.h>
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.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 start, curr;
printf("New thread started\n");
pthread_cleanup_push(cleanup_handler, NULL);
curr = start = time(NULL);
while (!done) {
pthread_testcancel(); /* A cancellation point */
if (curr < time(NULL)) {
curr = time(NULL);
printf("cnt = %d\n", cnt); /* A cancellation 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)
こ の 文 書 に つ い て
こ の man ペ ー ジ は Linux man−pages プ ロ ジ ェ ク ト の リ リ ー ス 3.79 の 一 部 で あ る 。 プ ロ ジ ェ ク ト の 説 明 と バ グ 報 告 に 関 す る 情 報 は http://www.kernel.org/doc/man−pages/ に 書 か れ て い る 。