[ruby-list:48801] Re: setsid(2) と getsid(2)
From:
Tanaka Akira <akr@...>
Date:
2012-06-20 21:51:00 UTC
List:
ruby-list #48801
2012年6月20日 20:38 SATOH Fumiyasu <fumiyas@osstech.jp>:
> 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]