sem_getvalue()は成功するのにsem_wait()で失敗します
解決済
回答 2
投稿
- 評価
- クリップ 0
- VIEW 3,528
sem_wait(&thread_inf[cnt].sem)を使っているのですが、
実行結果が失敗になります。(strerror(errno)の結果は[Invalid argument]になります)
確認のため、直前で
sem_getvalue(&thread_inf[cnt].sem, &val)を実行すると、
こちらは成功します。
(遅れて実行されるスレッド側のsem_post(&thread_inf[cnt].sem)も返り値は成功になります)
このthread_infはグローバル変数として宣言して使用しているのですが、
どこかまずいところがあるのでしょうか?
原因・対応がわかりましたら、回答お願いいたします。
-
気になる質問をクリップする
クリップした質問は、後からいつでもマイページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
クリップを取り消します
-
良い質問の評価を上げる
以下のような質問は評価を上げましょう
- 質問内容が明確
- 自分も答えを知りたい
- 質問者以外のユーザにも役立つ
評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。
質問の評価を上げたことを取り消します
-
評価を下げられる数の上限に達しました
評価を下げることができません
- 1日5回まで評価を下げられます
- 1日に1ユーザに対して2回まで評価を下げられます
質問の評価を下げる
teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。
- プログラミングに関係のない質問
- やってほしいことだけを記載した丸投げの質問
- 問題・課題が含まれていない質問
- 意図的に内容が抹消された質問
- 過去に投稿した質問と同じ内容の質問
- 広告と受け取られるような投稿
評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。
質問の評価を下げたことを取り消します
この機能は開放されていません
評価を下げる条件を満たしてません
質問の評価を下げる機能の利用条件
この機能を利用するためには、以下の事項を行う必要があります。
- 質問回答など一定の行動
-
メールアドレスの認証
メールアドレスの認証
-
質問評価に関するヘルプページの閲覧
質問評価に関するヘルプページの閲覧
checkベストアンサー
+2
thread_inf[cnt].sem
に対して、sem_init
もしくはsem_open
をする必要があるのではないでしょうか。
sem_init
での例を書いてみました。
(GCC 4.8.3 Cygwinを使用)
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <pthread.h>
#include <semaphore.h>
sem_t sem;
void *thread_f();
int main()
{
pthread_t th;
int shared;
unsigned int value;
int r;
shared = 1;
value = 0;
r = sem_init(&sem, shared, value);
printf("r=%d, err=%s\n", r, strerror(errno));
r = sem_getvalue(&sem, &value);
printf("r=%d, err=%s\n", r, strerror(errno));
if (pthread_create(&th, NULL, thread_f, (void *)NULL))
{
printf("スレッドの生成に失敗\n");
return 1;
}
printf("sem_wait\n");
r = sem_wait(&sem);
printf("r=%d, err=%s\n", r, strerror(errno));
return 0;
}
void *thread_f() {
sleep(5);
printf("sem_post\n");
sem_post(&sem);
return (void *)NULL;
}
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
+1
不要な説明かも知れませんがセマフォについてです。sem_はそのライブラリ関数になります。スレッドは並列実行されるので共通資源へのアクセス(共通の初期化処理、スレッド共通の変数へのアクセス等)に排他制御が必要になるのかと思います。
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
15分調べてもわからないことは、teratailで質問しよう!
- ただいまの回答率 88.23%
- 質問をまとめることで、思考を整理して素早く解決
- テンプレート機能で、簡単に質問をまとめられる
2014/11/25 18:24
書き漏れていましたが、それぞれのthread_inf[cnt].semは
sem_init( &thread_inf[cnt].sem, 0, 0 )で初期化しております。
このときの返値は
ret:0/strerror(errno):Successになります。
sem_init( &thread_inf[cnt].sem, 1, 0 )も試してみましたが、
結果は変わらずでした。
2014/11/25 19:24
上記のコードはこちらでは正しく動作しましたので、これとほぼ同じコードなのでしたら、プログラミング以外の問題の可能性もあるかも知れません。
本物のコードを提示するのは難しいと思いますので、もし、再現する最小限のコードを提示していただければ、コードが問題なのか、環境依存の問題なのかを切り分けられる可能性はあります。
2014/11/25 20:47
typedef struct tagHOGE
{
BOOL a_flg;//Windowsから移植の都合でtypedef int BOOLしています
BOOL b_flg;//Windowsから移植の都合でtypedef int BOOLしています
//自作DBアクセスクラスです
dbAccess *pDB;
DWORD thread_no;//Windowsからの移植の都合でtypedef uint32_t DWORDしています
char logfile[80+1];
pthread_t id; //各スレッドのid
pthread_mutex_t mutex; // スレッド内調整用
sem_t sem1; // スレッド->メイン用
sem_t sem2; // メイン->スレッド用
}HOGE, *PHOGE;
の構成だったのですが、
sem_t sem1とsemt_sem2をいちばん上に持って行ったところ
sem_waitがret:0/strerror(errno):Successになりました。
他のメンバーの操作時にメモリ破壊をしているのかと、
sem1,sem2の位置を戻して他のメンバに対する処理をコメントアウトしたのですが、
この場合はret:-1/strerror(errno):Invalid argumentでした。
コメントアウト対象
(sem_init前)
sprintf(thread_inf[cnt].logfile, "./TESTED_MODULE.LOG");//<-文字列そのままです
(sem_init後)
thread_inf[cnt].b_flg = DISABLE; /*#define DISABLE 0*/
pthread_mutex_init( &thread_inf[cnt].mutex, NULL );
thread_inf[cnt].thread_no = cnt + 1;
thread_inf[cnt].pDB = new dbAccess;
thread_inf[cnt].b_flg = ENABLE; /*#define ENABLE 1*/
(thread_inf[cnt].a_flgは今動かしている範囲では操作していません)
一応動くには動きましたが、どっかにしわ寄せが出そうで。。。
2014/11/25 21:27
配列サイズは固定ですか?
2014/11/27 23:16
Windowsからに限らず、移植前はたまたま動いていたのが新しいOSに移植したら問題が顕在化したというケースはよくあります。
2014/12/07 11:09
HOGE thread_inf[THREAD_MAX_SIZE]で宣言しています。
(reallocなどはしておらず、THREAD_MAX_SIZEは今のところ1です)
初期化は最初にmemset( &thread_inf[cnt], 0x00, sizeof(HOGE))した後
それぞれの値を設定して使っています。
セマフォ変数はもともとWindows時代は
EventのPOST,WAITしていたところの代替で
今回の移植から使っています。
2014/12/07 16:45
地道にすべてのthread_infの操作前後で状態を見ていくしか思いつきません。
お役にたてずにすみません。