HP-UX General
1820641 メンバー
1804 オンライン
109626 解決策
新規ポスト

msgrcvについて

 
ess2
時折のアドバイザー

msgrcvについて

msgrcv関数を即時モードでコールしたところ、戻り値に-1(異常)が返却されましたが、errnoが更新されず0のままでした。

メッセージは受信していないので、処理は異常ではなく、正常の動作ともいえるのですが、これは仕様でしょうか?メッセージ無しに該当するerrno(35)が返却されるのが正解ではないのでしょうか?
5件の返信5
nadachi
レギュラーアドバイザー

msgrcvについて

> msgrcv関数を即時モードでコールしたところ、

> 戻り値に-1(異常)が返却されましたが、

> errnoが更新されず0のままでした。

HP-UXのrevisionや、具体的なコードがないのでなんともいえませんが、HP-UX 11.11 で以下のようなコードをコンパイル、実行すると、

#include

#include

struct mymsg {

long mtype; /* message type */

char mtext;

};

main()

{

int msg, ret, err;

struct mymsg msgbuf;

extern int errno;

msg = msgget(IPC_PRIVATE, 0666|IPC_CREAT);

if (msg == -1) {

perror("msgget");

exit(1);

}

printf("msg : %d\n", msg);

ret = msgrcv(msg,

(void *)&msgbuf,

1000,

0,

IPC_NOWAIT);

err = errno;

if (ret == -1) {

perror("msgrcv");

printf("errno : %d\n", err);

}

printf("ret = %d\n", ret);

msgctl(msg, IPC_RMID, (struct msqid_ds *)NULL);

}

$ cc msg.c

$ ./a.out

msg : 252

msgrcv: No message of desired type

errno : 35

ret = -1

message queue の id 252,

msgrcv の戻り値(ret)は -1 で、 errnoは

35。これは/usr/include/sys/errno.h では、

#define ENOMSG 35 /* No message of desired type */

ですので、戻り値も errno も適切に設定されているようです。

( ess2さんの場合、戻り値は -1 で、errno のみ0

ということですが、失礼ながらもしかしたら、

 ret = msgrcv(...);

if (ret == -1) {

printf("msgrcv failed with ret = %d\", ret);

printf("errno = %d\n", errno);

...

みたいなコードにしていませんか? errno が

msgrcv()の終わりで設定されても、それを保存していないと次のsystem call呼び出し(この例では printf()からwrite()が呼ばれる)により値が変わります。)

参考まで。
ess2
時折のアドバイザー

msgrcvについて

nadachiさんご回答ありがとうございます。

投稿していただいたサンプルプログラムを

こちらの環境(HPUX 11.11)で確認してみたところでは、正しく動作いたしました。

msgrcvの直後でperrorでエラーメッセージを表示させると確かにNo message of desired typeが表示されるのですが、errnoはやはり0が返されます。こんなことってあるのでしょうか?

nadachi
レギュラーアドバイザー

msgrcvについて

> msgrcvの直後でperrorでエラーメッセージを表示

> させると確かにNo message of desired typeが

> 表示されるのですが、errnoはやはり0が

> 返されます。こんなことってあるのでしょうか?

もしプログラムが、

 ret = msgrcv(...);

perror("msgrcv");

printf("%d\n", errno);

とかになっているのなら、perror()関数中で、

errnoをキーにして"No message of desired type"という文字列を見つけた後、write()システムコールで標準エラー出力に書きます。この標準エラー出力へのwriteが成功すれば、errno は 0 にセットされますので、その後の printf("%d\n", errno) では 0 が表示されます。

 ですので、msgrcv()が設定したerrnoの値を確認するには、msgrcv()から戻ってから、別なシステムコールを呼び出す前に、どこかにコピーしておかないとうまくいきません。ですので、サンプルでは、

ret = msgrcv(...);

err = errno;

にしてerrを表示するようにしてあります。これなら、他のシステムコールが呼ばれる余地はないはずですから。

ess2
時折のアドバイザー

msgrcvについて

自己解決しました。

マルチスレッドのアプリケーションの場合、

コンパイルオプションで-DREENTRANTを指定してコンパイルするとスレッド単位にerrnoが管理できるようになるとのことです。

nadachiさん、ご協力ありがとうございました。
nadachi
レギュラーアドバイザー

msgrcvについて

 なるほど、multi-threadアプリケーションでしたか。ess2さんがサンプルコードを載せなかったのも無理はありません(きっと大きいに違いない)。また、こちらも再現できなかったのも無理はない。

 解決できて良かったですね。