2012年6月21日

[ruby-list:48801] Re: setsid(2) と getsid(2)

2012年6月20日 20:38 SATOH Fumiyasu <fumiyas@xxxxx>:

> setsid(2) によると、EPERM になるのは呼び出したプロセスが既に
> プロセスリーダーの場合、と記載されています。それを確かめたくて
> Ruby で getsid(2) 相当で確認しようと思ったのですが、Process.getsid
> はないようです。需要がないからでしょうか?

getsid は POSIX の範囲外、というのはあるかもしれません。

SUS には入っているのですが。

> $ ruby1.9.1 -e 'p Process.getsid'
> -e:1:in `<main>': undefined method `getsid' for Process:Module (NoMethodError)
>
> それはともかく、Ruby プロセスの起動から終了までのシステムコール
> トレースを見たのですが、プロセスリーダーになっている様子が
> ありません。上記のように Process.setsid が失敗する原因は
> 何かわかりますでしょうか。

ジョブコントロールをサポートしたシェルを使っているのではないでしょうか。

そのようなシェルは、ジョブ (上記の例では ruby プロセス) の起動時に
プロセスをプロセスグループリーダに設定します。

% ruby -ve '
system("ps -o ppid,pid,pgid,sid,comm #{$$}")
p begin Process.setsid rescue $! end
system("ps -o ppid,pid,pgid,sid,comm #{$$}")'
ruby 2.0.0dev (2012-03-16 trunk 35049) [x86_64-linux]
PPID PID PGID SID COMMAND
3578 6284 6284 3578 ruby
#<Errno::EPERM: Operation not permitted>
PPID PID PGID SID COMMAND
3578 6284 6284 3578 ruby

最初の ps の結果ですでに PID == PGID であることから、
プロセスグループリーダであることがわかります。

サブシェルの中で実行すれば、
ruby プロセスはプロセスグループリーダーにならないので、
以下のように成功します。

% ( ruby -ve '
system("ps -o ppid,pid,pgid,sid,comm #{$$}")
p begin Process.setsid rescue $! end
system("ps -o ppid,pid,pgid,sid,comm #{$$}")'
echo)
ruby 2.0.0dev (2012-03-16 trunk 35049) [x86_64-linux]
PPID PID PGID SID COMMAND
6300 6301 6300 3578 ruby
6301
PPID PID PGID SID COMMAND
6300 6301 6301 6301 ruby

こちらでは、最初は PID != PGID で、2回目の ps では PGID, SID が
変わっているのがみてとれます。

ちなみに、echo しているのは、zsh がサブシェル内の最後のコマンドを
fork せずに exec する (tail call する) 挙動を避けるためです。

というわけで、むしろ問題は、なぜ perl は成功するのか、ということでしょう。

あと気がついたのですが、ruby を strace すると、setsid が成功したように
見えるのが謎です。(gdb では失敗が観測されるのですが)

% strace -e setsid ruby -ve 'p Process.setsid'
ruby 2.0.0dev (2012-03-16 trunk 35049) [x86_64-linux]
setsid() = 6310
6310
--
[田中 哲][たなか あきら][Tanaka Akira]


投稿者 xml-rpc : 2012年6月21日 06:51
役に立ちました?:
過去のフィードバック 平均:(0) 総合:(0) 投票回数:(0)
本記事へのTrackback: http://hoop.euqset.org/blog/mt-tb2006.cgi/111023
トラックバック
コメント
コメントする




画像の中に見える文字を入力してください。