- 1 名前:名無しさん@お腹いっぱい。 mailto:sage [2006/12/20(水) 22:11:47 ]
- Posixな糸に群がる亡者どものスレ。地獄の底でsage進行。
徳の高い人はpthread天国でも可。 ■前スレ pthread地獄 pc8.2ch.net/test/read.cgi/unix/1010933537/
- 62 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/07/12(土) 12:20:38 ]
- > 時間が巻き戻ると
そんな運用しないのが前提じゃないのか。 普通は進み方を遅らせて徐々に合わせるか、一気に合わせるなら シングルユーザモードもしくは他にそのへんに敏感なプロセスが 動いていないときにするものだと思うが。
- 63 名前:52 mailto:sage [2008/07/12(土) 12:26:43 ]
- 返事が遅れました。
やはり何らかの制御が必要ということですね。 みなさん、ありがとうございました。 もっと勉強してきます。
- 64 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/07/12(土) 13:38:59 ]
- >>62
そういう常識?が通用する業界もあるんだ。 言いたいことはわかるけど、pthreadなんぞ知ったこっちゃない オペレータやユーザにそんな制限かけられないことが多いのでは? 全然別のこと担当してる同じマシン上のプログラムに制限かけたり こっちから監視したりとかも無理な相談だなあ。 これがもしも、普通の個人がPCで使うソフトなら、 どのプログラムがpthread使ってるとか関係なく、 好きなときに時刻の調整くらいするよね?
- 65 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/07/12(土) 13:47:45 ]
- >>61
お前みたいな奴が、cond_relative_timedwait()で1秒って指定したのに 1.1秒で復帰してきた!クソが!って怒るから絶対時刻にしたんだよ。 pthreadsの待ちの時間の正確性なんて信頼できないんだから、この点について 議論してもあまり意味ないと思う。
- 66 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/07/12(土) 15:53:32 ]
- >>65
信頼できない、のレベルによるな。 俺の仕事では1秒以下のズレは全然許容できるレベルだな。 それ以下はリアルタイムOS使う世界だと思う。よく知らんけど。 タイムアウト1秒に指定しても、制御戻るのは1分後かも・・・なんてのは全く話にならない。
- 67 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/07/12(土) 16:52:10 ]
- >>64
だから、通常の運用だと ntp がゆっくり時間補正するようになっている。 >>62 の後半は例外的な運用だろ。 # 知識, 理解力, 謙虚な心 の全てが欠如してると今後辛いぞ。
- 68 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/07/12(土) 18:13:59 ]
- そりゃ、運用や通信プロトコルまで口出しできりゃ、なんでもできる。
あんまり具体的な例挙げても仕方ない気がするが、 半導体業界の某標準プロトコルで、工場のホストから受け取った時刻に 工場内の装置(OSは普通Windows)が問答無用で同期することは普通に行われている。 Linuxに移行したいとか軽率に言い出されるとやばいと思う。 時刻なんて人間に表示するためのもので 制御プログラムとかが依存していいもんじゃないと思うんだが。
- 69 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/07/12(土) 22:25:13 ]
- >>68はまるで自分の業界がスタンダードで世界中がそれを基準にすべきと
いわん勢いだけど、それが根本的に噛み合ってないといいかげんに気付いたらどうよ。
- 70 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/07/12(土) 23:03:27 ]
- >>68
そう言う特殊な要件があるなら、それに合うように作ればいいだけ。 ホストの時刻に影響されたくなければ、システム時刻とホストから受け取った 時刻を別々に管理するとか、やりようはいくらでもあるだろ。
- 71 名前:名無しさん@お腹いっぱい。 [2008/07/12(土) 23:41:27 ]
- 俺のためにみんなが喧嘩するのはもうたくさんだ
- 72 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/07/13(日) 01:28:38 ]
- >>68
なんだ、ただのシッタカだったのか、お前。
- 73 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/07/14(月) 12:27:38 ]
- > 半導体業界の某標準プロトコルで、工場のホストから受け取った時刻に
> 工場内の装置(OSは普通Windows)が問答無用で同期することは普通に行われている。 自分で書いているように、それはパソコン系の「普通」であって、 UNIX界隈の人間がその種の運用をすることは100%有り得ないから、 時刻が急に巻き戻ってタイムアウトまで1秒のはずが61秒かかっちゃったりする心配を あなたがする必要はない。 もしプロトコル上、工場のホストと同期する必要があれば、 システムクロックを変更するのではなく、 アプリケーションの実装でシステムクロックとリモートホストのクロックの差を管理する。 このようにUNIX系へ移行するとしてもちゃんと問題なく出来るから、 あなたは心配しなくてよい。
- 74 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/07/14(月) 12:45:33 ]
- POSIXがatomic increment/decrementをAPIとして規定しなかったのはなぜ?
mutexがあっても軽量なカウンタが不要になることはないわけで、 結局、みな独自に実装しているのだが。
- 75 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/07/14(月) 13:53:53 ]
- ここで聞かずpthreadsのインタフェースを決めた人に聞いてください。
そういうAPIが必須ならプラットフォームを変えることを検討してください。 どうしてもpthreadsに必要ならpthreadsを変えるべく努力してください。 それもいやなら文句言わず今使えるもので実装しなさい。
- 76 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/07/14(月) 14:56:12 ]
- 知らないと一言書けば済むことをなぜ4行にも渡って
- 77 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/07/14(月) 22:08:16 ]
- > アプリケーションの実装でシステムクロックとリモートホストのクロックの差を管理する。
俺が知りたいのは、特定の仕様のシステムを実現する方法じゃなくて、 他のプログラムが何していようが、 ユーザが好き勝手に時刻を変更しようが、 現在からN秒以内に条件が成立しなければ、アウトという監視は本当にできないのかってこと。 Pthread標準の枠内で。 時刻をいじってるプログラムと密に連携したり同期とれるとか、 そんなこと当てにできないし、したくもない。
- 78 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/07/14(月) 23:00:10 ]
- ああ、わかった。
要は、pthread の仕様バグを見つけた俺を誉めてくれと言うことね。 「お前は、偉いよ。」 これで十分だろ、もう出てくるな。
- 79 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/07/14(月) 23:55:03 ]
- だいたいUnixで「ユーザ」が時刻を好き勝手にいじれるわけねーだろ。
そういう権限を生身の人間に与えちゃってるとしたらその時点で頭おかしい。
- 80 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/07/15(火) 00:26:26 ]
- > そういう権限を生身の人間に与えちゃってるとしたらその時点で頭おかしい。
ちょっ、お前ン所のサーバー管理者はロボットかよ !!
- 81 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/07/15(火) 00:55:01 ]
- サーバ管理者が時刻を好き勝手にいじるような頭の沸いたサイトはどうにもできねーよ。pthread以前の問題。
- 82 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/07/15(火) 01:49:43 ]
- >>74
POSIXで規定されなかった理由は知らんが、 C++0xではちゃんと Atomic operation や Memory barrier が 定義されるから安心しろ。
- 83 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/07/15(火) 09:21:07 ]
- ちなみにWin32のWaitForMultipleObjectsは相対時間指定なので
>>59の"Timed Wait Semantics"に挙げられた問題が存在する。 >>61をみると理解できていないようなので、何が問題なのかわかるまで考えた方がよいだろう。 プロセスのプリエンプション自体が問題なのではないので、絶対指定のPOSIXにはこの問題はない。
- 84 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/07/15(火) 09:25:58 ]
- >>82
Cで頼む
- 85 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/07/15(火) 12:11:40 ]
- Cに入れるようなもんじゃないだろう。
pthread_xxx_npあたりでいいよ。 CASとかもセットで。
- 86 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/07/15(火) 15:46:11 ]
- >>85
pthread_xxx_npあたりで頼む
- 87 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/07/18(金) 10:56:20 ]
- Solaris10なんだけど、マルチスレッドのプロセスからコールされる
サブルーチンをコンパイルする時って、どんなコンパイルオプションを 付ければ良いんですか? 普通に、コンパイルして共有ライブラリを作ればよい? このサブルーチンの中では、pthread_XXXはコールしていないので、 #include <pthread.h> もしてないんですがこれってダメ?
- 88 名前:87 mailto:sage [2008/07/18(金) 10:59:53 ]
- ちなみに、そのサブルーチンは複数のスレッドから同時に呼ばれても
大丈夫な様に作ってあります。
- 89 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/07/18(金) 14:33:31 ]
- なにもいらないと思うけど。
引数だけで計算して値を返すとか、完全に状態に依存しないものならね。
- 90 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/07/18(金) 15:12:22 ]
- Sun cc使ってる場合は-mtが必要になったりする。
docs.sun.com/app/docs/doc/819-0390/compile-94179?a=view これは-D_REENTRANT -lthreadと等価なようだ。 gccであっても、使っているライブラリによっては、同様に何らかのシンボル定義が 必要になるかもしれない。
- 91 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/07/19(土) 11:43:35 ]
- int f(int a, int b) {
return a + b; } でも?
- 92 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/07/19(土) 15:22:04 ]
- gcc風に言えば__attribute_((const))な関数なら特別なコンパイラフラグは不要。
- 93 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/07/22(火) 12:01:15 ]
- 複数のスレッドの終了を待つってどう書くんですか?
マルチプロセスだと、waitpid(2)とかで複数の子プロセスの終了を 待てるんですが、pthread_join()だと、特定のスレッドの終了しか待てません。 例えば、 100個の子プロセスを作成して、親プロセスはwaitpid()で任意の子プロセスの終了を 監視していて、特定の子プロセスが死んだ場合に、そのプロセスの再起動(fork())を 行うという処理を、pthreadで書こうとした場合、どうすれば良いんでしょうか? そもそも、上記の様な考え方は、プロセスの親子関係が前提となっているので、 この考え方を、親子という関係のないpthreadに持って来る事がおかしいのでしょうか?
- 94 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/07/22(火) 12:38:18 ]
- 死ぬとき親に何か通知したら?
勝手に死ぬなら、たまにpthread_kill(thread_id, 0)するとか。
- 95 名前:93 mailto:sage [2008/07/22(火) 13:21:54 ]
- それだと、作成したスレッドが死ぬようなイベントが発生したタイミングを
捕まえるという動作ではないですよね。(ポーリングっぽい) 例えば、100個スレッドを作って、その各スレッドがTCPソケットを使って 通信していて、TCPコネクションがcloseされたので、pthread_exit()を コールしたとか、、ソケットから受け取ったデータを処理している最中に SIGSEGVで死んだとかした場合に、これら100個のスレッドを常に監視 していて、死んだスレッドを再度作成したいって感じの処理をすっきりと 書きたい場合ってどうやるんでしょう? スレッドじゃなくてプロセスだったら、子プロセスがexit(2)した場合も、 子プロセスが、SIGSEGVで死んだ場合も、親プロセスがwaitpid(2)してれば 子プロセスが死んだタイミングで親プロセスはそれを知ることが出来るじゃ ないですか。 これと同じような事をpthreadでやりたいんですが、なんかよく判らんのです。
- 96 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/07/22(火) 14:09:26 ]
- SIGSEGVなどで「死ぬ」場合はプロセスごと道連れなので、pthreads的な対処は
無意味では? そう考えていくと、スレッドが自発的に終了するケースだけを扱えばいいわけなので、 (スレッドプール的な構成なら)条件変数での通知・待機を使えばよさそうに思う。
- 97 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/07/22(火) 14:17:14 ]
- そう。プロセスと異なり、スレッドは勝手に死んだりしない。だから終了を監視する
必要もない。個々のスレッドは処理が終わったら終了するのではなく、次の処理要求 を待って休眠するように書く方がよいだろう。
- 98 名前:93 mailto:sage [2008/07/22(火) 14:58:19 ]
- >>96
>>97 確かに、SIGSEGVなどで死ぬ場合は、SIGSEGVを発生させたロジックを実行中のスレッド のみが死ぬわけではなく、プロセス自体がいなくなりますが、これをハンドリングして 特定のスレッドのみを再起動して処理を継続するってのは変でしょうか? プログラムのバグも含めて考えると、やっぱりスレッドがSIGSEGVするケースも考慮して おきたんです。 Webサーバの様なプログラムをマルチスレッドで書くとすると、クライアントから送られて来た データがメタメタでサーバ側の処理がSIGSEGVしてしまったとか。(だったらちゃんとデータを 処理する前にチェックしろってのは、ちょっと置いといて。) こういったケースで正常なクライアントとのコネクションも全部潰れてしまうのは、なんだかなぁ って思ったんです。
- 99 名前:93 mailto:sage [2008/07/22(火) 15:06:19 ]
- あと、条件変数でスレッド間で待ち合わせを行うってのはなんとなく判るんですが、
それと、スレッドの終了を待つってのがどうもうまく結び付きません。 例えば、 ワーカースレッドがもうダメポってpthread_cond_signal()をコール。 メインスレッドは、pthread_cond_wait()で待ってる。 ワーカースレッドはどのタイミングでpthread_exit()をコールすればいいの? メインスレッドは、どのタイミングでpthread_join()をコールすればいいの? ワーカースレッドが居なくなったタイミングって条件件数を使えばメインスレッドで 捕まえることって出来ますか? なんか、この辺りがよく判らんのです。
- 100 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/07/22(火) 15:24:43 ]
- 不正なポインタが使用されないよう入力の厳密なチェックを追加するか、普通
にプロセスで書くのをお薦めする。Apacheでも普通に使われているのを見れば わかるように、UNIXのプロセスはそれほど遅くない。 どうしてもpthreadで書きつつsignalが捕捉したいのなら止めないが、 "pthread地獄"のスレタイは伊達や酔狂ではないので。
- 101 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/07/22(火) 15:58:43 ]
- >>98
SIGSEGVを発生させるようなことをしたスレッドを、どうやって特定する? たぶん難しいと思うから、そんなの実装するよりは真面目に入力のチェックを 実装した方がずっと簡単だと思うけどなぁ。 内部だけで使うプログラムならいいけど、セキュリティ的にもあれだし。
- 102 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/07/22(火) 16:12:40 ]
- >>101
いちおうSIGSEGVは「踏んだ」スレッドに飛ぶのでそれはわかる。 たぶん、正しくリソースを解放して終了するのが難しい。
- 103 名前:93 mailto:sage [2008/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なんかのスレッドだと出来るらしいし。
- 104 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/07/22(火) 16:38:33 ]
- 端的に言えば、基本的な考え方が間違ってるよ。
別に間違ってちゃいかんというわけではないが、そっちは地獄方面。
- 105 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/07/22(火) 16:41:24 ]
- >>102
1:1な実装とかだと、踏んだスレッドにSIGSEGVが飛びそうなのは想像できるんですが、 それがどういうレベルで保証されてるか、もし知ってたら教えて欲しいです。 SUSとかの仕様でそのあたりの挙動は定義されてましたっけ?
- 106 名前:93 mailto:sage [2008/07/22(火) 18:20:41 ]
- >>105
どういうレベルかと言われると良く判らないのですが、 SIGSEGVとか、SIGILLとか、SIGFPEとかのシグナルは、同期シグナルと呼ばれていて、 スレッド側で、signal(3)でハンドラを設定しておいてあげれば、そのシグナルを発生させた スレッドがシグナルを受け取ってくれるみたいです。 "pthread 同期シグナル" でぐぐった時の2ページ目の最後のマルチスレッドのプログラミング というSunのPDFへのリンク先の資料に書いてありました。 Solaris10(x86)と、FreeBSD(i386)でサンプルを作ってみたところ、スレッド側で定義した シグナルハンドラでpthread_self()すると、ちゃんとしたスレッドIDが取得できました。
- 107 名前:93 mailto:sage [2008/07/22(火) 18:55:40 ]
- ちゃんとしたスレッドIDってのは、SIGSEGVを発生させたスレッドIDって言う意味です。
- 108 名前:105 mailto:sage [2008/07/22(火) 20:40:51 ]
- >>106
ありがとうございます。 comp.programming.threads FAQにも、 Q40: Which signals are synchronous, and whicn are are asynchronous? というのがあって、同じような記述がされてました。 POSIXとかの仕様として挙動がちゃんと決まっているなら、安心してこの性質が使える と思うのですが、実装依存と言われると便利だけど使いにくいなぁと思ったもので…
- 109 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/07/23(水) 09:00:47 ]
- 使うべきなのは条件変数じゃなくてセマフォ。
子スレッドは終了時にsemaphoreを解放して、 管理スレッドはsemaphoreを得てスレッド作ればいいだけの話。 シグナルハンドラから安全にpthread_*呼び出せるかどうかは知らんがな。 やろうとも思わん。
- 110 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/07/24(木) 00:03:24 ]
- 条件変数とmutexがあればセマフォも実装できるから同じことだよ。
mutex で保護したカウンタを、スレッド数で初期化して作っておいて、 待つ側のスレッドはそのカウンタが0になるまでpthread_cond_wait()、 終了するスレッドは、pthread_exit()する直前にカウンタをデクリメント、 もしカウンタがゼロになったらpthread_cond_signal()すればいいだけ。 かんたん。 pthread_join()は使う必要ない。 あとSIGSEGVが起きているということは、そのプロセス内のメモリ空間は ぶち壊れて不整合が起きているってことだから、さっさとプロセスごと 死ぬべき。そんな状態で動作を続けたら、誤動作して余計悲惨なことに なるのがオチ。
- 111 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/07/24(木) 01:25:25 ]
- まあ、世の中にはsigaltstack(2)というものもあるわけでね。
SEGVから戻ってこれるケースもあるわけで、そこまで言いきるのはどうかな。
- 112 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/07/24(木) 02:29:58 ]
- 確かにそういうケースもあるにはあるな。
>>98は明らかにそういうケースじゃないけどな。
- 113 名前:93 mailto:sage [2008/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);
- 114 名前:93 mailto:sage [2008/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);
- 115 名前:93 mailto:sage [2008/07/24(木) 09:51:36 ]
- やっと、条件変数の使い方が判った。
添削してもらおうとは思ってないけど、とりあえずいろいろ教えてもらったので 張っときます。 複数の子プロセスの任意のタイミングでの終了を親プロセスが待つって いうケース(親がwaitpid(2)で任意の子プロセスの終了を待つ)を想定してます。
- 116 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/07/24(木) 10:44:00 ]
- 子が正しく死ぬなら、semaphoreでやるのが楽そうではある。
- 117 名前:93 mailto:sage [2008/07/24(木) 11:24:46 ]
- セマフォでやるってのがいまいちピンと来ないんだけど。
親(メイン)スレッドがいつ居なくなるか判らない複数の子(ワーカー)スレッドの終了を待っていて どれかの子(ワーカー)が居なくなったら、それをハンドリング(どの子が居なくなったかを認識)するってどうやるの?
- 118 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/07/24(木) 11:37:20 ]
- わかりにくいし余計なスレッド起床も伴うから
条件変数は使いまわさず親スレッド起床用と子スレッド起床用とで分けた方がよくね?
- 119 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/07/24(木) 11:46:43 ]
- 勘違いしてた。単純に死んだのを取りこぼさずに知りたいわけではないのか。
じゃあやっぱcondかな。
- 120 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/07/24(木) 12:01:12 ]
- 作ってdetachして放置。
子から親になにか渡さないといけないなら、親側に渡してから死ぬ。
- 121 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/07/24(木) 12:04:34 ]
- 子スレッドの数だけ充足するならsemaphore、
ハンドリングまでするならqueueだな。 どちらもmutexとcondition variableで書けるのはいいとして、 pthreadでの標準的な実装はないのかな?
- 122 名前:93 mailto:sage [2008/07/24(木) 12:52:22 ]
- >>118
最初はそう考えたんですが、親がcond_waitしてないときに子が親にcond_signal するケースを考えると、なんか余計に複雑になるような気がして、 >>113 >>114 に落ち着いたんです。 条件変数分けると、mutexも分けないといけないし。 (ん? 条件変数だけ分けてmutexは使い回せばよい?) もっかい考えてみる。 >>120 ケースバイケースだと思うんだけど、pthreadでプログラム作るときって、detachするのが どっちかと言うとデフォなの? >>121 そうなんですよね。 こんなのって定石だと思うんですが、なんでpthread_XXが無いんだろう?
- 123 名前:93 mailto:sage [2008/07/24(木) 13:11:48 ]
- >>121
>ハンドリングまでするならqueueだな。 あー、確かに、queue作って、子が死ぬ前に突っ込んで親がそれを拾えば うまくいきますね。 子が居なくなるのと親がそれを検出するのの同期を取らなくても良い場合は、 それが一番良さそうな気がしますね。
- 124 名前:名無しさん@お腹いっぱい。 [2008/07/24(木) 13:38:01 ]
- >>121
セマフォは普通にPOSIXのセマフォ使えばいいよね
- 125 名前:93 mailto:sage [2008/07/24(木) 13:50:31 ]
- >>118
こんな感じですか。 ワーカー側でcond_broadcast使わなくても良くなったので、無駄なスレッドが 起こされなくなってちょっと軽くなったのかな。 ボス側 pthread_mutex_lock(&m_end); while (0 != thread_num) { while(NULL == thr_end) { pthread_cond_wait(&c_end_boss, &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_work); } pthread_mutex_unlock(&m_end); ワーカー側 pthread_mutex_lock(&m_end); while (NULL != thr_end) { pthread_cond_wait(&c_end_work, &m_end); } thr_end = pthread_self(); pthread_cond_signal(&c_end_boss); pthread_mutex_unlock(&m_end); pthread_exit((void *)NULL);
- 126 名前:93 mailto:sage [2008/07/24(木) 19:31:08 ]
- pthreadとシグナルについてですが、
同期シグナルは発生要因となったスレッドに送られ、そのスレッド上でシグナルハンドラが起動される。 非同期シグナルは、それを受け取る準備をしているスレッドに送られる。(結果的に、同期的にシグナルを扱うことが出来る) いずれの場合も、シグナルを受け取ったスレッドでpthread_XXを使ってもうまく動くと思うんですが、間違ってますか? ようは、SIGSEGVのハンドラからpthread_XXを呼んでみるとうまく動いているように見えるんだけど、 これって、実装(環境)依存なだけなのか、そうでないのかが知りたいんです。
- 127 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/07/25(金) 02:27:24 ]
- 実装依存以前どころか、たんに運がいいだけである可能性が高いな。
SIGSEGVが起きる状況の場合、SIGSEGVのきっかけとなったメモリ破壊の結果、 pthread_mutex_tやpthread_cond_tまで巻きぞえをくらって壊れている可能性 がある。その状況でpthread関数を呼んでちゃんと動く保証なんてありえない。 シグナルハンドラから呼ばれて正常動作する保証があるのは、マニュアルに async-signal-safeと明記されている関数だけ。 そういう関数は、実際のところはシステムコールであることが多い。
- 128 名前:93 mailto:sage [2008/07/25(金) 10:14:40 ]
- 確かにそういうケースだとpthread関数がまともに動く可能性はないかもしれないですね。
私がSIGSEGVを発生させたパターンは単に、NULLアドレスに書き込んでるだけなので、 その辺のデータ(pthread関数が使用している内部データ)を壊してるって訳ではないです。 そもそも、シグナルハンドラからPthread関数が呼べない理由ってのは何故なんでしょう? Pthread関数の内部データはそのスレッドのスタック上に存在していて、 シグナルハンドラはスレッドとは別のスタックを使って実行されるからって事ですか?
- 129 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/07/25(金) 11:07:22 ]
- 仮にシグナルハンドラからpthread_*が完全に問題なく呼べたとしても、
mutexとかのリソース持ってる状態でシグナル発生したら状態復旧は絶望的だお。
- 130 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/07/25(金) 11:13:24 ]
- おれもわざわざそんな茨の道に行かなくてもと思う。
- 131 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/07/25(金) 11:44:36 ]
- そこまで苦労してまでバグを直接修正したくない理由の方に興味がわいてきた。
- 132 名前:93 mailto:sage [2008/07/25(金) 12:44:25 ]
- 今、気になっているのは、Webサーバの様なサーバプログラムで、ボスは常にaccept()待ち。
クライアントからの接続があったら、ワーカーを起動して、そのあとの処理はワーカに任せる。 といった、定番的なネットワークサーバを書く場合に、いわゆるfork()モデルと、スレッドモデルで どのような差があるのか(特にエラー発生時において)という事です。 なので、ワーカー側の処理ってのは、基本的に独立していてワーカー同士で共有を行うデータも 不要であると考えています。 非同期シグナルも使う必要は無いと考えています。(多分) fork()モデルの場合は、ワーカプロセスが同期シグナル(SIGSEGV,SIGILL等)を発生させたとしても、 他のワーカープロセスへの影響は特に無く、再度クライアントが接続してくれば、また、サービスを 再開することが出来ます。 スレッドモデルで同じことを実装することは可能なのか? 特定のワーカーが何らかの理由で同期シグナルを発生させた場合、その特定のワーカが死ぬのは しょうがないと思うんですが、他のワーカーまで道連れにしてしまうのは避けたいと思っています。 スレッドモデルを使ってこのような処理を安全に書けないって事は無いんじゃないのって思うんですが、 いかがなもんでしょう? また、MySQLはマルチスレッドで動いているらしいのですが、こういったDBサーバは更に複数のワーカ間で データの排他や同期を取る必要があると思うんですが、こういったプログラムは同期シグナルとどうやって 折り合いをつけているんでしょうか。 これがいわゆる茨の道ってやつですか?
- 133 名前:93 mailto:sage [2008/07/25(金) 12:52:01 ]
- >>131
まだ、なにも作ってないですよ。 pthreadというか、マルチスレッドのプログラムを作るのが始めてなので、 いろいろサンプルを作って勉強している最中です。 このスレとっても勉強になります。 レスしてくださっている皆さんありがと。 ところで、本屋行っても、pthread(マルチスレッド)に関する書籍ってほとんどないですよね。 あっても、10年ぐらい前に出版されたものが殆んどで。 この先、CPUはメニィコアに進もうとしているからもっと沢山あっても良いと思うんですが、 pthreadってあんまり使わないんですかね?
- 134 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/07/25(金) 12:57:45 ]
- > スレッドモデルで同じことを実装することは可能なのか?
想定しているのがSIGSEGVやSIGILLのようなプログラムロジックの バグである限り、不可能というのが答。 プロセスには、スレッドに比べて、メモリ空間が分離されていて SIGSEGVやSIGILLのような誤動作の影響を完全に排除できるという 特徴がある。つまり、まさにプロセスの利点に当てはまるケースな わけで、このような想定状況で、スレッドにプロセスと同等の信頼性 を求めることはできない。 > こういったプログラムは同期シグナルとどうやって折り合いをつけて > いるんでしょうか。 バグが原因で発生するシグナルは別として、sigwait() で対処するのが常識。
- 135 名前:93 mailto:sage [2008/07/25(金) 13:40:09 ]
- >>134
そっか。 やっぱりそうなんですか。 非同期シグナルであれば、シグナル受け専のスレッドを立てておいて、そこで sigwait()するってのは判るんですが、同期シグナルはsigwait()では待てないですもんね? ん?待てるのか? ちょっと試してみる。 でも、待てたとしても、どのスレッドがその同期シグナルを発生させたかって、シグナル受け専 スレッドで判らないけりゃどうしようもないですし。
- 136 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/07/26(土) 12:58:41 ]
- 悪いこといわねえだ。signal扱いたいならprocess村に帰った方がええ。
- 137 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/07/26(土) 17:23:08 ]
- つ libevent
- 138 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/07/26(土) 19:24:07 ]
- libevent はマルチスレッド環境でも安全に使う方法があるってだけで、
それ自体がスレッドセーフな作りになってるってわけじゃなかったはず。
- 139 名前:93 mailto:sage [2008/07/29(火) 10:32:25 ]
- とりあえず、やってみました。(Solaris10 x86です。)
ボス側で全てのシグナルをブロックし、シグナル受信専用スレッドを作成し、そこでsigwait()。 ワーカースレッドでSGISEGVを発生させるために、NULLアドレスに書き込み。 結果は、プロセスごと終了。 同期シグナルは発生元のスレッドに送られるのでシグナル受信専用スレッドでsigwait()していても 捕まえる事が出来ないってことですね。 同期シグナルは、ワーカースレッド側でsigset()して、シグナルハンドラ側でボスに >>125 すれば、 とりあえずハンドリングは出来ますが、 >>127 にもあるように、どこまで動くのかは不明ですね。 >>134 にもあるように、この辺りがマルチスレッドと、マルチプロセスの差という事なんですね。 そもそもスレッドってなに?、スタックとスレッドの関係って?、プロセスとスレッドの関係って? OSはスレッドをどう認識してるの? なんてことが判っている人にとっては自明なんでしょうが、私にもようやくこの辺りが判って来た 様な気がします。 なかなか使いどころが難しいですが、面白い仕組みですね。
- 140 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/07/30(水) 21:16:41 ]
- シグナルのことを考えるとunixでスレッドをモリモリ使うのはキツい。角度とか。
- 141 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/08/09(土) 19:15:44 ]
- あと、子プロセス生成(fork)も相性が悪くて、深い悲しみに包まれた。
- 142 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/08/09(土) 20:02:32 ]
- マルチスレッドプログラミング→排他漏れ続出→永遠とバグが取れない→いくえ不明
- 143 名前:名無しさん@お腹いっぱい。 [2008/08/09(土) 20:41:21 ]
- 俺はマルチプロセスを使い手なんだが相手が残念な事にスレッドを使ってきたので「お前それで良いのか?」と言うと「何いきなり話かけて来てるわけ?」と言われた。
俺の弟がスレッドの熟練者なのだがおれはいつも勝つから相手が気の毒になったので聞いただけなんだがむかついたので「お前シグナルでボコるわ・・」と 言ってmain直後に力を溜めてkillしたら多分リアルでビビったんだろうな、、pthread_sigmaskしてたからサスペンドしてカカッっとforkしながらkillしたらかなり青ざめてた おれは一気にlongjmpしたんだけどスレッドが硬直してておれの動きを見失ったのか動いてなかったからコマンド投下で排他を崩した上についげきのデッドロックでさらにダメージは加速した。 わざとセマフォをとり「俺はこのままタイムアウトでもいいんだが?」というとようやく必死な顔してなんかコードのはしっこからブロック型システムコール出してきた。 おれはselectで回避、これは一歩間違えるとカウンターで大ダメージを受ける隠し技なので後ろのギャラリーが拍手し出した。 俺は「うるさい、気が散る。一瞬の油断が命取り」というとギャラリーは黙った スレッドは必死にやってくるが、時既に時間切れ、スタックガードを固めた俺にスキはなかった たまに来るスタックガードでは防げない攻撃もexitで撃退、終わる頃にはズタズタにされたメモリ空間のcoreがいた
- 144 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/08/10(日) 03:35:51 ]
- MTは処理効率も応答性もいいのでプログラマからは良くたよりにされる
だがたよりにされたいからMTに分けてもダメだと言う事が最近わかった MTに分けるのは真にMTの問題だから処理を分けたくて分割するんじゃない 分かれてしまう処理がMT GUIはざんねんがはっきりいってmutexはつかわないしAPIもMT-unsafeとかイマイチだから信頼されにくい
- 145 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/08/15(金) 13:04:59 ]
- これ以上スレッドを作るなよ
プロセスはお前等のためにメモリ空間提供してやってるんだからな プロセスが終了すればすぐ死ぬくせに調子こき過ぎ あまり調子に乗ってると裏世界でひっそり幕を閉じる
- 146 名前:名無しさん@お腹いっぱい。 [2008/10/09(木) 04:28:39 ]
- hosyu
|

|