Python の subprocess の preexec_fn の実装と fork のスレッドセーフティー問題

22
ふみやす@シェルまおう(自称でない) @satoh_fumiyasu

OpenLDAP slapd はマルチスレッドで slapd-shell(5) (シェルバックエンド) は fork & exec してシェル起動している。何か工夫しているんだろうか? slapo-ppolicy 用パスワード検査モジュールを自作したのだが、そいつでは特に何も…。

2013-03-24 02:57:32
ふみやす@シェルまおう(自称でない) @satoh_fumiyasu

slapd-shell(5) は使ったことないし、どうせ誰も使ってないだろうから問題があっても発覚していないだろうけど。

2013-03-24 02:58:34
小崎 資広 (KOSAKI Motohiro) @kosaki55tea

@satoh_fumiyasu fork & execしたら安全ですよ。execしたあとは libc lockもなにもすべて綺麗サッパリ消えてしまうのでなにやってもOKに戻ります

2013-03-24 03:00:34
ふみやす@シェルまおう(自称でない) @satoh_fumiyasu

fork & exec が何やっているのか、知っているのは概要くらいで、実際何ごちゃごちゃやっているのか知らないので、どうして async signal safe なのしか駄目なのか想像できない。 https://t.co/WXFZlpqukD

2013-03-24 03:01:42
methane @methane

@kosaki55tea あー、大抵のマルチスレッドプログラムはIO待ちのためにスレッド使ってるんで、 fork-exec じゃない fork は使い物になりませんねぇ。。。

2013-03-24 03:04:04
小崎 資広 (KOSAKI Motohiro) @kosaki55tea

@methane もちろん libc lock の構造はlibcに依存するので libcの内部構造にものすごく詳しいとOS依存で刺さらないコードを書くことは可能です。たとえば僕ならglibc依存でいいなら書けると思う

2013-03-24 03:05:33
methane @methane

@satoh_fumiyasu malloc が内部でロックを取得している最中に別スレッドが fork すると、子プロセスでは malloc を呼び出していたスレッドが消え去るのでロックだけが残ってしまいます。

2013-03-24 03:05:48
methane @methane

@kosaki55tea でも最近は Linux の libc も glibcだけじゃなくて eglibc, android の libc とかありますもんね。。。

2013-03-24 03:07:21
小崎 資広 (KOSAKI Motohiro) @kosaki55tea

@methane です。だから実質的には無理だと思います

2013-03-24 03:07:44
ふみやす@シェルまおう(自称でない) @satoh_fumiyasu

@kosaki55tea わかったような気がします。ほかのスレッドを libc ロックしてない状態で一時停止して fork …とか実装すればよいのかな。難しい、面倒 and/or 遅いかな。よくわからんが…。

2013-03-24 03:12:37
methane @methane

@satoh_fumiyasu Linuxではforkしたスレッド以外は消え去りますね。Posix全部かどうかは知りません。forkしたタイミングが正確にわかるのはforkしたスレッドだけなので、他のスレッドまでコピーされるとそれはそれで怖いことが起こると思います。

2013-03-24 03:13:32
SKS rep @repeatedly

LINQっぽいのD言語に欲しい.まぁRangeで頑張るという手もあるが…

2013-03-24 03:17:41
SKS rep @repeatedly

それとは別にRubyとPythonのfork戦略についてのやりとりが…誰かまとめてくれんかね

2013-03-24 03:19:27
ふみやす@シェルまおう(自称でない) @satoh_fumiyasu

カーネルとか libc とかそのレベルのレイヤーを読み書きしている人は、やっぱり強そうだなー。座学程度なら知っているんだが、足りないなー。

2013-03-24 03:21:44
kuenishi @kuenishi

fork/execの間に何か処理ができてしまうのはイロイロよくないですよ。どうせやりたいことはforkじゃなくてpopenなのだから、みんなErlang/OTPを見習うべき

2013-03-24 03:21:59
SKS rep @repeatedly

@kuenishi Erlang/OTPはfork/exec使ってないんです?

2013-03-24 03:23:16
ふみやす@シェルまおう(自称でない) @satoh_fumiyasu

pthread なコードはいくらか読めてちょっとしたパッチを書いたことはあるけど、自分で実装したことはない。

2013-03-24 03:23:46
kuenishi @kuenishi

@repeatedly fork(2)やexec(3)を生で呼び出せなくしてあるよ。popenみたいなことしてパイプで通信する代わりにメッセージを送ったり受け取ったりするだけかな。

2013-03-24 03:25:40
kuenishi @kuenishi

いま気付いた。forkはセクション2でexecはセクション3だ。

2013-03-24 03:25:53
SKS rep @repeatedly

@kuenishi ほほぅ.ErlangのレイヤーからはそもそもAPIとして提供してなくて,触れないという感じですかね.

2013-03-24 03:26:46
SKS rep @repeatedly

なるほど.まぁ言語によってAPI変わってくるし,軽量プロセスとかみたいないわゆる強力なメッセージングの仕組みがすでにあるのであれば,確かにいらないのかもしれん.

2013-03-24 03:28:39
kuenishi @kuenishi

@repeatedly Rubyで、fork/execをプリミティブに見せてるのってProcを渡してメモリをいじることなく簡単に実行できるようにするため、とかそういう理解で合ってる? それとも単にシステムコールは全部そうしてある?

2013-03-24 03:30:04
SKS rep @repeatedly

@kuenishi 知りません!CとかPerlにあったからそのまま持ってきたんでは?と思ってますが,今だとspawnとかあったりで,forkをガチで使っている人は減ってきているイメージですが,なんとも…

2013-03-24 03:34:22