トップページunix
213コメント82KB

pthread地獄 part 2

■ このスレッドは過去ログ倉庫に格納されています
0001名無しさん@お腹いっぱい。2006/12/20(水) 22:11:47
Posixな糸に群がる亡者どものスレ。地獄の底でsage進行。
徳の高い人はpthread天国でも可。
■前スレ
 pthread地獄
 http://pc8.2ch.net/test/read.cgi/unix/1010933537/
0023名無しさん@お腹いっぱい。2007/05/15(火) 00:00:56
>>22
今までのM:Nスレッドライブラリはlibkseという名前で残っているから
シンボリックリンクを張り替えるなどすればいい。

libkseは少なくとも7.x系までは生き残るだろうけど、
8-currentあたりで消されそうな気もする。
0024名無しさん@お腹いっぱい。2007/05/15(火) 10:04:12
libmap.conf じゃ駄目なのか?
0025名無しさん@お腹いっぱい。2007/05/16(水) 07:27:30
つかえないというのは
いいところなしというつもりでした。
複雑な制御の割に性能が出ないのでしょうか。
Solarisも1:1になったし。
0026名無しさん@お腹いっぱい。2007/05/16(水) 07:42:38
前スレで擁護してた奴の言い訳が聞きたいところだが…
0027名無しさん@お腹いっぱい。2007/05/22(火) 08:02:39
javaみたいにスレッドをCPU数に関係なくたくさんつくるやつの性能も1:1で満足できるのか知りたい。
0028名無しさん@お腹いっぱい。2007/06/10(日) 00:00:13
言い訳よりも、ベンチの結果とかが欲しいね。
Apache (worker) + DB とかの。
0029名無しさん@お腹いっぱい。2007/06/11(月) 15:38:16
SunStudio11や12もいいよ。
何せ無償だし。OpenMPもあるでよ。
0030名無しさん@お腹いっぱい。2008/03/13(木) 00:37:42
Remove kernel support for M:N threading.
http://lists.freebsd.org/pipermail/cvs-src/2008-March/088489.html
0031名無しさん@お腹いっぱい。2008/03/13(木) 10:41:17
このスレ忘れてた…
0032名無しさん@お腹いっぱい。2008/03/13(木) 16:53:54
いまやpthreadを生で使うことはほとんどないからなぁ。
0033名無しさん@お腹いっぱい。2008/03/18(火) 11:07:37
純粋に興味があるんだけどpthread以外って何使ってる?
0034名無しさん@お腹いっぱい。2008/03/18(火) 22:18:18
javaのスレッド
最近はjava.util.concurrentがあるからね。
0035名無しさん@お腹いっぱい。2008/03/19(水) 18:46:40
>>34
1.5の時はメモリリークに悩まされました>concurrent周り
0036名無しさん@お腹いっぱい。2008/06/06(金) 15:37:18
mutexを使って資源の共有ではなく、単にスレッド間の同期を取りたいのですが、
デッドロックしないようにするにはどのように書けばよいのでしょうか?
0037名無しさん@お腹いっぱい。2008/06/06(金) 15:46:12
pthread_barrier_waitがあるのにmutexが使いたいと申すか
0038名無しさん@お腹いっぱい。2008/06/09(月) 15:07:17
たくさんのthreadをpthread_create()で作成する場合、
作成した子スレッドへの引数ってどうやって渡せば良いんでしょうか?
   for (narg = 0; narg < 100; ++narg) {
      nrc = pthread_create(&t1, NULL, tfunc, (void *)&narg);
   }

こんな感じで渡そうとしたんですが、作成された子スレッド(tfunc)側で
引数を使おうとすると、親スレッド側でどんどん値がインクリメントされて
いってしまいます。(並列に動いてるんだから当然なんでしょうけど。)
0039名無しさん@お腹いっぱい。2008/06/09(月) 15:34:40
値そのものをパラメータとして(void *)にキャストして渡す、
もしくはスレッド数分の配列に格納してその要素へのポインタを渡す。

というか、あなたはまだマルチスレッドプログラミングに手を出すのは早い。
そんなんではデバッグも満足にできないから、
基礎をしっかりやってからの方が近道。
0040382008/06/09(月) 16:06:42
>>39
レスTHX
>もしくはスレッド数分の配列に格納してその要素へのポインタを渡す。
やってみたら、ちゃんと渡りました。

この時に確保しておくスレッド数分の配列って、ヒープにとるもの?
それとも、親スレッド側のスタックにとるもの?
それとも、グローバル変数もしくはスタティック変数としてとるもの?
それとも、ケースバイケース?

子スレッド実行中にそのエリア(子スレッド用の引数エリア)が開放
されなければ良いと思うんだけど、親スレッド側のスタックにとった
場合ってどうなるんでしょうか?

親スレッドは子スレッドがすべて終了するまで存在するとした場合、
親スレッド側のスタックにとったエリアを子スレッドへの引数エリアと
して使用するのはOKでしょうか?

>基礎をしっかりやってからの方が近道。
今が基礎のつもりです。
0041名無しさん@お腹いっぱい。2008/06/09(月) 22:05:04
このスレのタイトルは上手く考えられているな。
pthread_createでスレッドに渡す引数の渡し方を人に聞くというのは、
地獄に入口から一歩入ったところで、番犬ケルベロスに向かって
「この先にお弁当屋さんはありますか?」と聞いているような、不思議な感じが醸し出される。

>>40
実際のメモリマップを想像すれば、答えは自ずとわかる。
MTは単一のプロセス空間内でPCとスタックを複数切り替えるだけで、マジックはない。
0042名無しさん@お腹いっぱい。2008/06/10(火) 12:24:05
void*に入るなら、キャストして渡した方が後のこと考えないで良いから楽ちん。

親のスタックに取ったら、その寿命考えないといけないから面倒。
個別にヒープにとってアドレス渡して、その領域の後片付けも子スレッドがすれば良いんじゃない。

場合によっては、1スレッドに必要な領域*スレッド数をまとめて取って、
子スレッドがすべて終了したら、親がまとめて捨てても良いと思うけど。
0043名無しさん@お腹いっぱい。2008/06/11(水) 02:48:23
pthreadsなんで単純なsleep/wakeupインターフェースないのん?
0044名無しさん@お腹いっぱい。2008/06/11(水) 23:36:23
>>43
mutexを直前まで持ったままsleepできないとwakeupの取りこぼしがおこるから。
基礎から勉強しなおしてね
0045サカムラ・アントワネット2008/06/12(木) 02:15:33
とりこぼしちゃまずいなら、μITRONのwup_tskみたいにキューイングすればいいじゃない
0046名無しさん@お腹いっぱい。2008/06/12(木) 11:27:18
それ何てセマフォ?
0047名無しさん@お腹いっぱい。2008/06/13(金) 08:46:34
キャンセルができるみたい。
0048名無しさん@お腹いっぱい。2008/06/17(火) 10:56:17
マルチスレッドプログラミングに関する書籍で良書と言われている
ものってどんなものがあるんでしょうか?

この本は良いよってのがあれば紹介して頂けると嬉しいです。
0049名無しさん@お腹いっぱい。2008/06/18(水) 15:55:48
Patterns for Parallel Programming
0050名無しさん@お腹いっぱい。2008/06/19(木) 13:50:07
CSPモデルの理論
0051名無しさん@お腹いっぱい。2008/06/19(木) 15:27:45
javaだけど
Java並行処理プログラミング
Doug Leaも書いてる
0052名無しさん@お腹いっぱい。2008/07/09(水) 22:12:50
外部のカウンタ変数をひとつ用意して、
複数のスレッドで、それをインクリメントするだけのときも
mutex使った方がいいのでしょうか。
0053名無しさん@お腹いっぱい。2008/07/09(水) 23:01:05
extern int i;
foo() {
...
i++; /* is it atomic? *?
...
}
が atomic operation かどうかは処理系による。
++/-- だけなら mutex よりも semaphore の方がいい気がする。
cf. sem_init(3)
0054名無しさん@お腹いっぱい。2008/07/10(木) 00:29:47
>>52
IA32ですら、その手のことをアセンブリ言語レベルで正しく実装する場合に
LOCKプレフィクス付きでインクリメントしなきゃならなかったりする。
何らかの排他制御は必要。
0055名無しさん@お腹いっぱい。2008/07/10(木) 01:52:53
volatileで十分w
0056名無しさん@お腹いっぱい。2008/07/10(木) 12:09:34
インクリメントするのが一人なら確かに十分。

mutexはまあ確実だけど、性能の要求によってはspinとかrwlockとか。
semaphoreは、規定回数処理するっていうならいいけど、
回数が分からない場合どうするの?
0057名無しさん@お腹いっぱい。2008/07/11(金) 10:19:44
冗談なのか何なのか知らないがインクリメント対象に volatile なんて付けたら
read-modify-write なコードになると思うんだが。
0058名無しさん@お腹いっぱい。2008/07/11(金) 23:36:36
cond_timedwaitがシステム時刻を要求するのは問題があると思うけど、
少なくとも日本語ではそういう情報が見当たらない。
wait中にシステム時刻が変更されたらどうなるんだろう。
どう考えてもSUNのcond_reltimedwait_npみたいなのが標準化されるべきだと
思うけど、そういう動きはないんだろうか。
標準のtimedwaitでどうエミュレーションしてもバグの潰し様が無いはず。
0059名無しさん@お腹いっぱい。2008/07/12(土) 01:40:32
相対値はそれはそれでまずいんだよ。
標準はなんも考えずにシステムクロックを採用してるわけじゃなくて、
あれはあれでちゃんと角度とか考えられてるんだ。
http://www.opengroup.org/onlinepubs/000095399/functions/pthread_cond_wait.html
のRATIONALE読んでね。
0060名無しさん@お腹いっぱい。2008/07/12(土) 05:25:18
読んだ。
>a relative time measure can be easily implemented
on top of a function that specifies absolute time
ダウト。任意のタイミングによるシステム時刻変更を考えれば
これが実装できないから問題にしている。
現在時刻取得 -> timespec変数にタイムアウト値加算
-> timedwait()に渡す -> wait中
全ての過程で競合が発生するだろ?
時間が進むことでタイムアウトが早く発生するのはまあ、対処できる。
(無駄にコードが複雑になるけど。)
しかし、時間が巻き戻ると、タイムアウトの発生が遅れてしまう。
制御が戻らないことには何もできない。
異常時に即座に実行しないといけない処理が遅れてしまう。
0061名無しさん@お腹いっぱい。2008/07/12(土) 05:26:02

さらに、逆のパターンの実装は競合が発生するという主張について、
> clock_gettime(CLOCK_REALTIME, &now)
> reltime = sleep_til_this_absolute_time -now;
> cond_relative_timed_wait(c, m, &reltime);
> If the thread is preempted between the first statement
> and the last statement, the thread blocks for too long. Blocking,
> however, is irrelevant if an absolute timeout is used.
これもよく分からん。
このコードの間のプリエンプトが問題になるハードリアルタイムシステムなら
リアルタイムOS使わないと無理じゃないの?
まあ、絶対時刻指定のAPIが要らないとまでは云わない。

> An absolute timeout also need not be
> recomputed if it is used multiple times in a loop
これもダメ、システム時刻の変更があり得る状況では、
システム時刻によって、ある時点から何秒経過したか知ることはできない。
タイムアウト内で、条件成立前にシグナルされる可能性がある場合、
俺の場合は、仕事ではWindowsなので、GetTickCount()を使い、
システム起動からの経過時間を元に次のタイムアウト指定値を求める。
Unixならプロセスの使用時間を取得できるAPIがあったはず。
0062名無しさん@お腹いっぱい。2008/07/12(土) 12:20:38
> 時間が巻き戻ると

そんな運用しないのが前提じゃないのか。
普通は進み方を遅らせて徐々に合わせるか、一気に合わせるなら
シングルユーザモードもしくは他にそのへんに敏感なプロセスが
動いていないときにするものだと思うが。
0063522008/07/12(土) 12:26:43
返事が遅れました。
やはり何らかの制御が必要ということですね。
みなさん、ありがとうございました。
もっと勉強してきます。
0064名無しさん@お腹いっぱい。2008/07/12(土) 13:38:59
>>62
そういう常識?が通用する業界もあるんだ。
言いたいことはわかるけど、pthreadなんぞ知ったこっちゃない
オペレータやユーザにそんな制限かけられないことが多いのでは?
全然別のこと担当してる同じマシン上のプログラムに制限かけたり
こっちから監視したりとかも無理な相談だなあ。

これがもしも、普通の個人がPCで使うソフトなら、
どのプログラムがpthread使ってるとか関係なく、
好きなときに時刻の調整くらいするよね?
0065名無しさん@お腹いっぱい。2008/07/12(土) 13:47:45
>>61
お前みたいな奴が、cond_relative_timedwait()で1秒って指定したのに
1.1秒で復帰してきた!クソが!って怒るから絶対時刻にしたんだよ。

pthreadsの待ちの時間の正確性なんて信頼できないんだから、この点について
議論してもあまり意味ないと思う。

0066名無しさん@お腹いっぱい。2008/07/12(土) 15:53:32
>>65
信頼できない、のレベルによるな。
俺の仕事では1秒以下のズレは全然許容できるレベルだな。
それ以下はリアルタイムOS使う世界だと思う。よく知らんけど。
タイムアウト1秒に指定しても、制御戻るのは1分後かも・・・なんてのは全く話にならない。
0067名無しさん@お腹いっぱい。2008/07/12(土) 16:52:10
>>64
だから、通常の運用だと ntp がゆっくり時間補正するようになっている。

>>62 の後半は例外的な運用だろ。

# 知識, 理解力, 謙虚な心 の全てが欠如してると今後辛いぞ。
0068名無しさん@お腹いっぱい。2008/07/12(土) 18:13:59
そりゃ、運用や通信プロトコルまで口出しできりゃ、なんでもできる。
あんまり具体的な例挙げても仕方ない気がするが、
半導体業界の某標準プロトコルで、工場のホストから受け取った時刻に
工場内の装置(OSは普通Windows)が問答無用で同期することは普通に行われている。
Linuxに移行したいとか軽率に言い出されるとやばいと思う。
時刻なんて人間に表示するためのもので
制御プログラムとかが依存していいもんじゃないと思うんだが。
0069名無しさん@お腹いっぱい。2008/07/12(土) 22:25:13
>>68はまるで自分の業界がスタンダードで世界中がそれを基準にすべきと
いわん勢いだけど、それが根本的に噛み合ってないといいかげんに気付いたらどうよ。
0070名無しさん@お腹いっぱい。2008/07/12(土) 23:03:27
>>68
そう言う特殊な要件があるなら、それに合うように作ればいいだけ。

ホストの時刻に影響されたくなければ、システム時刻とホストから受け取った
時刻を別々に管理するとか、やりようはいくらでもあるだろ。
0071名無しさん@お腹いっぱい。2008/07/12(土) 23:41:27
俺のためにみんなが喧嘩するのはもうたくさんだ
0072名無しさん@お腹いっぱい。2008/07/13(日) 01:28:38
>>68
なんだ、ただのシッタカだったのか、お前。
0073名無しさん@お腹いっぱい。2008/07/14(月) 12:27:38
> 半導体業界の某標準プロトコルで、工場のホストから受け取った時刻に
> 工場内の装置(OSは普通Windows)が問答無用で同期することは普通に行われている。

自分で書いているように、それはパソコン系の「普通」であって、
UNIX界隈の人間がその種の運用をすることは100%有り得ないから、
時刻が急に巻き戻ってタイムアウトまで1秒のはずが61秒かかっちゃったりする心配を
あなたがする必要はない。

もしプロトコル上、工場のホストと同期する必要があれば、
システムクロックを変更するのではなく、
アプリケーションの実装でシステムクロックとリモートホストのクロックの差を管理する。
このようにUNIX系へ移行するとしてもちゃんと問題なく出来るから、
あなたは心配しなくてよい。
0074名無しさん@お腹いっぱい。2008/07/14(月) 12:45:33
POSIXがatomic increment/decrementをAPIとして規定しなかったのはなぜ?
mutexがあっても軽量なカウンタが不要になることはないわけで、
結局、みな独自に実装しているのだが。
0075名無しさん@お腹いっぱい。2008/07/14(月) 13:53:53
ここで聞かずpthreadsのインタフェースを決めた人に聞いてください。
そういうAPIが必須ならプラットフォームを変えることを検討してください。
どうしてもpthreadsに必要ならpthreadsを変えるべく努力してください。
それもいやなら文句言わず今使えるもので実装しなさい。
0076名無しさん@お腹いっぱい。2008/07/14(月) 14:56:12
知らないと一言書けば済むことをなぜ4行にも渡って
0077名無しさん@お腹いっぱい。2008/07/14(月) 22:08:16
> アプリケーションの実装でシステムクロックとリモートホストのクロックの差を管理する。

俺が知りたいのは、特定の仕様のシステムを実現する方法じゃなくて、
他のプログラムが何していようが、
ユーザが好き勝手に時刻を変更しようが、
現在からN秒以内に条件が成立しなければ、アウトという監視は本当にできないのかってこと。
Pthread標準の枠内で。
時刻をいじってるプログラムと密に連携したり同期とれるとか、
そんなこと当てにできないし、したくもない。
0078名無しさん@お腹いっぱい。2008/07/14(月) 23:00:10
ああ、わかった。

要は、pthread の仕様バグを見つけた俺を誉めてくれと言うことね。

「お前は、偉いよ。」

これで十分だろ、もう出てくるな。
0079名無しさん@お腹いっぱい。2008/07/14(月) 23:55:03
だいたいUnixで「ユーザ」が時刻を好き勝手にいじれるわけねーだろ。
そういう権限を生身の人間に与えちゃってるとしたらその時点で頭おかしい。
0080名無しさん@お腹いっぱい。2008/07/15(火) 00:26:26
> そういう権限を生身の人間に与えちゃってるとしたらその時点で頭おかしい。

ちょっ、お前ン所のサーバー管理者はロボットかよ !!
0081名無しさん@お腹いっぱい。2008/07/15(火) 00:55:01
サーバ管理者が時刻を好き勝手にいじるような頭の沸いたサイトはどうにもできねーよ。pthread以前の問題。

0082名無しさん@お腹いっぱい。2008/07/15(火) 01:49:43
>>74
POSIXで規定されなかった理由は知らんが、
C++0xではちゃんと Atomic operation や Memory barrier が
定義されるから安心しろ。
0083名無しさん@お腹いっぱい。2008/07/15(火) 09:21:07
ちなみにWin32のWaitForMultipleObjectsは相対時間指定なので
>>59の"Timed Wait Semantics"に挙げられた問題が存在する。
>>61をみると理解できていないようなので、何が問題なのかわかるまで考えた方がよいだろう。
プロセスのプリエンプション自体が問題なのではないので、絶対指定のPOSIXにはこの問題はない。
0084名無しさん@お腹いっぱい。2008/07/15(火) 09:25:58
>>82
Cで頼む
0085名無しさん@お腹いっぱい。2008/07/15(火) 12:11:40
Cに入れるようなもんじゃないだろう。
pthread_xxx_npあたりでいいよ。
CASとかもセットで。
0086名無しさん@お腹いっぱい。2008/07/15(火) 15:46:11
>>85
pthread_xxx_npあたりで頼む
0087名無しさん@お腹いっぱい。2008/07/18(金) 10:56:20
Solaris10なんだけど、マルチスレッドのプロセスからコールされる
サブルーチンをコンパイルする時って、どんなコンパイルオプションを
付ければ良いんですか?

普通に、コンパイルして共有ライブラリを作ればよい?

このサブルーチンの中では、pthread_XXXはコールしていないので、
#include <pthread.h> もしてないんですがこれってダメ?
0088872008/07/18(金) 10:59:53
ちなみに、そのサブルーチンは複数のスレッドから同時に呼ばれても
大丈夫な様に作ってあります。
0089名無しさん@お腹いっぱい。2008/07/18(金) 14:33:31
なにもいらないと思うけど。
引数だけで計算して値を返すとか、完全に状態に依存しないものならね。
0090名無しさん@お腹いっぱい。2008/07/18(金) 15:12:22
Sun cc使ってる場合は-mtが必要になったりする。
http://docs.sun.com/app/docs/doc/819-0390/compile-94179?a=view

これは-D_REENTRANT -lthreadと等価なようだ。

gccであっても、使っているライブラリによっては、同様に何らかのシンボル定義が
必要になるかもしれない。
0091名無しさん@お腹いっぱい。2008/07/19(土) 11:43:35
int f(int a, int b) {
 return a + b;
}
でも?
0092名無しさん@お腹いっぱい。2008/07/19(土) 15:22:04
gcc風に言えば__attribute_((const))な関数なら特別なコンパイラフラグは不要。
0093名無しさん@お腹いっぱい。2008/07/22(火) 12:01:15
複数のスレッドの終了を待つってどう書くんですか?
マルチプロセスだと、waitpid(2)とかで複数の子プロセスの終了を
待てるんですが、pthread_join()だと、特定のスレッドの終了しか待てません。

例えば、
100個の子プロセスを作成して、親プロセスはwaitpid()で任意の子プロセスの終了を
監視していて、特定の子プロセスが死んだ場合に、そのプロセスの再起動(fork())を
行うという処理を、pthreadで書こうとした場合、どうすれば良いんでしょうか?

そもそも、上記の様な考え方は、プロセスの親子関係が前提となっているので、
この考え方を、親子という関係のないpthreadに持って来る事がおかしいのでしょうか?
0094名無しさん@お腹いっぱい。2008/07/22(火) 12:38:18
死ぬとき親に何か通知したら?
勝手に死ぬなら、たまにpthread_kill(thread_id, 0)するとか。
0095932008/07/22(火) 13:21:54
それだと、作成したスレッドが死ぬようなイベントが発生したタイミングを
捕まえるという動作ではないですよね。(ポーリングっぽい)

例えば、100個スレッドを作って、その各スレッドがTCPソケットを使って
通信していて、TCPコネクションがcloseされたので、pthread_exit()を
コールしたとか、、ソケットから受け取ったデータを処理している最中に
SIGSEGVで死んだとかした場合に、これら100個のスレッドを常に監視
していて、死んだスレッドを再度作成したいって感じの処理をすっきりと
書きたい場合ってどうやるんでしょう?

スレッドじゃなくてプロセスだったら、子プロセスがexit(2)した場合も、
子プロセスが、SIGSEGVで死んだ場合も、親プロセスがwaitpid(2)してれば
子プロセスが死んだタイミングで親プロセスはそれを知ることが出来るじゃ
ないですか。

これと同じような事をpthreadでやりたいんですが、なんかよく判らんのです。
0096名無しさん@お腹いっぱい。2008/07/22(火) 14:09:26
SIGSEGVなどで「死ぬ」場合はプロセスごと道連れなので、pthreads的な対処は
無意味では?

そう考えていくと、スレッドが自発的に終了するケースだけを扱えばいいわけなので、
(スレッドプール的な構成なら)条件変数での通知・待機を使えばよさそうに思う。
0097名無しさん@お腹いっぱい。2008/07/22(火) 14:17:14
そう。プロセスと異なり、スレッドは勝手に死んだりしない。だから終了を監視する
必要もない。個々のスレッドは処理が終わったら終了するのではなく、次の処理要求
を待って休眠するように書く方がよいだろう。
0098932008/07/22(火) 14:58:19
>>96
>>97
確かに、SIGSEGVなどで死ぬ場合は、SIGSEGVを発生させたロジックを実行中のスレッド
のみが死ぬわけではなく、プロセス自体がいなくなりますが、これをハンドリングして
特定のスレッドのみを再起動して処理を継続するってのは変でしょうか?
プログラムのバグも含めて考えると、やっぱりスレッドがSIGSEGVするケースも考慮して
おきたんです。

Webサーバの様なプログラムをマルチスレッドで書くとすると、クライアントから送られて来た
データがメタメタでサーバ側の処理がSIGSEGVしてしまったとか。(だったらちゃんとデータを
処理する前にチェックしろってのは、ちょっと置いといて。)

こういったケースで正常なクライアントとのコネクションも全部潰れてしまうのは、なんだかなぁ
って思ったんです。
0099932008/07/22(火) 15:06:19
あと、条件変数でスレッド間で待ち合わせを行うってのはなんとなく判るんですが、
それと、スレッドの終了を待つってのがどうもうまく結び付きません。

例えば、
ワーカースレッドがもうダメポってpthread_cond_signal()をコール。
メインスレッドは、pthread_cond_wait()で待ってる。
ワーカースレッドはどのタイミングでpthread_exit()をコールすればいいの?
メインスレッドは、どのタイミングでpthread_join()をコールすればいいの?

ワーカースレッドが居なくなったタイミングって条件件数を使えばメインスレッドで
捕まえることって出来ますか?

なんか、この辺りがよく判らんのです。
0100名無しさん@お腹いっぱい。2008/07/22(火) 15:24:43
不正なポインタが使用されないよう入力の厳密なチェックを追加するか、普通
にプロセスで書くのをお薦めする。Apacheでも普通に使われているのを見れば
わかるように、UNIXのプロセスはそれほど遅くない。

どうしてもpthreadで書きつつsignalが捕捉したいのなら止めないが、
"pthread地獄"のスレタイは伊達や酔狂ではないので。
0101名無しさん@お腹いっぱい。2008/07/22(火) 15:58:43
>>98
SIGSEGVを発生させるようなことをしたスレッドを、どうやって特定する?
たぶん難しいと思うから、そんなの実装するよりは真面目に入力のチェックを
実装した方がずっと簡単だと思うけどなぁ。
内部だけで使うプログラムならいいけど、セキュリティ的にもあれだし。
0102名無しさん@お腹いっぱい。2008/07/22(火) 16:12:40
>>101
いちおうSIGSEGVは「踏んだ」スレッドに飛ぶのでそれはわかる。

たぶん、正しくリソースを解放して終了するのが難しい。
0103932008/07/22(火) 16:20:14
>>100
>>101
ワーカースレッドとは別にsignalをハンドルするスレッドを、1つもしくは、
ワーカースレッド数分作成しておけば、どのワーカースレッドがSIGSEGV
を発生させたかは判るような気がしてます。

とりあえず、signalはちょっと置いといて、複数のワーカースレッドが
居なくなったタイミング(pthread_exit()をコールしたタイミング)で
メインスレッドがpthread_join()をコールする仕組み(=waitpid())を
作ってみたんですが、単純にpthread_cond_signal()をワーカースレッドで
呼ぶだけだと、メインスレッドがpthread_cond_wait()を実行中じゃない
ケースでとりこぼしちゃうんですね。

メインスレッドがちゃんとpthread_cond_wait()を実行しているタイミングを
ワーカースレッドが認識しないとダメなのか。

なんか、基本的な考え方が間違っている様な気がしてきました。
そもそも、pthread_join()が複数のスレッドを待てない時点で、この様な
事をやりたいという考えがそもそも変な気がしてるんですが、でも、
Windowsなんかのスレッドだと出来るらしいし。
0104名無しさん@お腹いっぱい。2008/07/22(火) 16:38:33
端的に言えば、基本的な考え方が間違ってるよ。
別に間違ってちゃいかんというわけではないが、そっちは地獄方面。
0105名無しさん@お腹いっぱい。2008/07/22(火) 16:41:24
>>102
1:1な実装とかだと、踏んだスレッドにSIGSEGVが飛びそうなのは想像できるんですが、
それがどういうレベルで保証されてるか、もし知ってたら教えて欲しいです。
SUSとかの仕様でそのあたりの挙動は定義されてましたっけ?
0106932008/07/22(火) 18:20:41
>>105
どういうレベルかと言われると良く判らないのですが、
SIGSEGVとか、SIGILLとか、SIGFPEとかのシグナルは、同期シグナルと呼ばれていて、
スレッド側で、signal(3)でハンドラを設定しておいてあげれば、そのシグナルを発生させた
スレッドがシグナルを受け取ってくれるみたいです。
"pthread 同期シグナル" でぐぐった時の2ページ目の最後のマルチスレッドのプログラミング
というSunのPDFへのリンク先の資料に書いてありました。

Solaris10(x86)と、FreeBSD(i386)でサンプルを作ってみたところ、スレッド側で定義した
シグナルハンドラでpthread_self()すると、ちゃんとしたスレッドIDが取得できました。
0107932008/07/22(火) 18:55:40
ちゃんとしたスレッドIDってのは、SIGSEGVを発生させたスレッドIDって言う意味です。
01081052008/07/22(火) 20:40:51
>>106
ありがとうございます。
comp.programming.threads FAQにも、
Q40: Which signals are synchronous, and whicn are are asynchronous?
というのがあって、同じような記述がされてました。

POSIXとかの仕様として挙動がちゃんと決まっているなら、安心してこの性質が使える
と思うのですが、実装依存と言われると便利だけど使いにくいなぁと思ったもので…
0109名無しさん@お腹いっぱい。2008/07/23(水) 09:00:47
使うべきなのは条件変数じゃなくてセマフォ。
子スレッドは終了時にsemaphoreを解放して、
管理スレッドはsemaphoreを得てスレッド作ればいいだけの話。

シグナルハンドラから安全にpthread_*呼び出せるかどうかは知らんがな。
やろうとも思わん。
0110名無しさん@お腹いっぱい。2008/07/24(木) 00:03:24
条件変数とmutexがあればセマフォも実装できるから同じことだよ。

mutex で保護したカウンタを、スレッド数で初期化して作っておいて、
待つ側のスレッドはそのカウンタが0になるまでpthread_cond_wait()、
終了するスレッドは、pthread_exit()する直前にカウンタをデクリメント、
もしカウンタがゼロになったらpthread_cond_signal()すればいいだけ。
かんたん。
pthread_join()は使う必要ない。

あとSIGSEGVが起きているということは、そのプロセス内のメモリ空間は
ぶち壊れて不整合が起きているってことだから、さっさとプロセスごと
死ぬべき。そんな状態で動作を続けたら、誤動作して余計悲惨なことに
なるのがオチ。
0111名無しさん@お腹いっぱい。2008/07/24(木) 01:25:25
まあ、世の中にはsigaltstack(2)というものもあるわけでね。
SEGVから戻ってこれるケースもあるわけで、そこまで言いきるのはどうかな。
0112名無しさん@お腹いっぱい。2008/07/24(木) 02:29:58
確かにそういうケースもあるにはあるな。
>>98は明らかにそういうケースじゃないけどな。
0113932008/07/24(木) 09:46:56
複数のワーカースレッドの終了を待つロジックを書いてみた。

   /* 全てのワーカースレッドの終了を待つ */
   pthread_mutex_lock(&m_end);
   while (0 != thread_num) {
      while(NULL == thr_end) {
         pthread_cond_wait(&c_end, &m_end);
      }
      nrc = pthread_join(thr_end, NULL);
      if (0 == nrc) {
         fprintf(stdout, "thread %5d is exited...\n", thr_end);
         --thread_num;
         thr_end = NULL;
      }else{
         fprintf(stdout, "Error pthread_join() return %d\n", nrc);
      }
      pthread_cond_broadcast(&c_end);
   }
   pthread_mutex_unlock(&m_end);
   fprintf(stdout, "ALL thread is exited... thread_num=%d\n", thread_num);
0114932008/07/24(木) 09:47:40
こっちがワーカースレッド側

   /* メインスレッドに処理終了を通知 */
   pthread_mutex_lock(&m_end);
   while (NULL != thr_end) {
      pthread_cond_wait(&c_end, &m_end);
   }
   thr_end = pthread_self();
   pthread_cond_broadcast(&c_end);
   pthread_mutex_unlock(&m_end);
   pthread_exit((void *)NULL);
0115932008/07/24(木) 09:51:36
やっと、条件変数の使い方が判った。
添削してもらおうとは思ってないけど、とりあえずいろいろ教えてもらったので
張っときます。

複数の子プロセスの任意のタイミングでの終了を親プロセスが待つって
いうケース(親がwaitpid(2)で任意の子プロセスの終了を待つ)を想定してます。
0116名無しさん@お腹いっぱい。2008/07/24(木) 10:44:00
子が正しく死ぬなら、semaphoreでやるのが楽そうではある。
0117932008/07/24(木) 11:24:46
セマフォでやるってのがいまいちピンと来ないんだけど。
親(メイン)スレッドがいつ居なくなるか判らない複数の子(ワーカー)スレッドの終了を待っていて
どれかの子(ワーカー)が居なくなったら、それをハンドリング(どの子が居なくなったかを認識)するってどうやるの?
0118名無しさん@お腹いっぱい。2008/07/24(木) 11:37:20
わかりにくいし余計なスレッド起床も伴うから
条件変数は使いまわさず親スレッド起床用と子スレッド起床用とで分けた方がよくね?
0119名無しさん@お腹いっぱい。2008/07/24(木) 11:46:43
勘違いしてた。単純に死んだのを取りこぼさずに知りたいわけではないのか。
じゃあやっぱcondかな。
0120名無しさん@お腹いっぱい。2008/07/24(木) 12:01:12
作ってdetachして放置。
子から親になにか渡さないといけないなら、親側に渡してから死ぬ。
0121名無しさん@お腹いっぱい。2008/07/24(木) 12:04:34
子スレッドの数だけ充足するならsemaphore、
ハンドリングまでするならqueueだな。
どちらもmutexとcondition variableで書けるのはいいとして、
pthreadでの標準的な実装はないのかな?
0122932008/07/24(木) 12:52:22
>>118
最初はそう考えたんですが、親がcond_waitしてないときに子が親にcond_signal
するケースを考えると、なんか余計に複雑になるような気がして、
>>113
>>114
に落ち着いたんです。
条件変数分けると、mutexも分けないといけないし。
(ん? 条件変数だけ分けてmutexは使い回せばよい?)
もっかい考えてみる。

>>120
ケースバイケースだと思うんだけど、pthreadでプログラム作るときって、detachするのが
どっちかと言うとデフォなの?

>>121
そうなんですよね。
こんなのって定石だと思うんですが、なんでpthread_XXが無いんだろう?
■ このスレッドは過去ログ倉庫に格納されています