ちょっと先の未来クイズ第4問

現在、下記のようなプログラムを作成しています。
内容は、メッセージキューを受信するスレッドを生成するというイメージです。
処理内容は下記のようになります。
 (1)メッセージキューの生成
 (2)スレッド生成(メッセージキュー受信側)
 (3)スレッド停止
 (4)メッセージキューの削除

しかし、(3)のスレッド停止を実施しても、(4)のメッセージキューの削除以降にて、msgrcvのエラーが出力されてしまいます。
スレッド停止を行ったことから、TestThreadは動作しなくなり、(4)のメッセージキューの削除にて、エラーともならずに終了することを望んでりますが、上手くいきません。
下記に作成しているプログラムを記載いたします。
正常終了をするには何がいけないのでしょうか?
ご教授宜しくお願い致します。

[test.cc]
----------------------------------------------------------------
#include <time.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <ctype.h>
#include <stdlib.h>
#include <pthread.h>
#include <stdlib.h>
#include <sys/ipc.h>
#include <sys/msg.h>

// メソッドポインタ定義
typedef void (*testT);

// スレッドID
pthread_t threadId;
// メッセージキュー識別子
int msqId;

// 送受信するメッセージ
struct msgbuf{
long int type;
char data[BUFSIZ];
};

// テストスレッド
void TestThread()
{
// メッセージ
struct msgbuf message;

while( 1 )
{
printf("### TEST ###\n");
printf("msq start\n");
// 受信
if( msgrcv( msqId, &message, BUFSIZ, 0, 0 ) == -1)
{
printf("ERR! msgrcv errno[%d]\n", errno);
continue;
}
printf("msq ed\n");
sleep(1);
}
return;
}

// メイン
int main(int argc, char *argv[])
{
// メッセージキュー識別子退避変数
int testMsqid;
// スレッド操作リターン値
int status;
// スレッドa用のパラメータ
pthread_t thread_test;

printf("### TEST START ###\n");

// メッセージキューの作成
if( (testMsqid = msgget((key_t)1111, 0666 | IPC_CREAT)) == -1 )
{
printf("ERR! CREATE bkMsqId[%d]\n", testMsqid);
return 1;
}
// メッセージキュー識別子を共通変数に設定
msqId = testMsqid;
printf("msgget OK\n");
sleep(5);

// スレッドを生成
status = pthread_create(&thread_test, NULL, (void*(*)(void*))TestThread, (void*)NULL);
if(status!=0)
{
printf("pthread_create ng\n");
return 1;
}
printf("pthread_create OK\n");
sleep(5);

// スレッド停止
status = pthread_cancel(thread_test);
// スレッド停止結果
if ( status != 0 )
{
printf("pthread_cancel ng\n");
return 1;
}
printf("pthread_cancel OK\n");
sleep(5);

// メッセージキューの削除
if ( msgctl( msqId, IPC_RMID, NULL) == -1 )
{
printf("msqId[%d] errno[%d]\n", msqId, errno);
return 1;
}
printf("msgctl OK\n");
sleep(5);

printf("### TEST E N D ###\n");
return 0;
}
----------------------------------------------------------------

A 回答 (1件)

1.スレッドのcanceltypeが


 PTHREAD_CANCEL_DEFERRED(デフォルト値)
の場合、そのスレッドは次のcancellation pointまで止まりません。

2. IPCのmsgrcv()が 安全な cancellation point になるかどうかは怪しいです。(実装依存で結果不定が正解だと思います。)

対策としては、明示的に cancellation point
 ~pthread_testcancel()など~
を埋め込むのが確実でしょう。
    • good
    • 0
この回答へのお礼

ご教授ありがとうございます。

msgrcvはキャンセルポイントであると思っておりました。
明示的にキャンセルポイントを埋め込むと、可能であるのですね。

逆に、スレッドのcanceltypeが
PTHREAD_CANCEL_ASYNCHRONOUS
(取り消し要求が届くと直ちに呼び出しスレッドを取り消す)
であると、直ちに取り消すということになるのですよね?
2種類の方法があると思われますので、両方とも試してみたいと思います。

大変有り難う御座いました。

お礼日時:2008/02/23 10:53

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人はこんなQ&Aも見ています


おすすめ情報