天泣記

2012-06-07 (Thu)

#1

ふと、fork が失敗したときに ruby がどう振る舞うか調べてみた。

% ruby -v
ruby 2.0.0dev (2012-01-10 trunk 34265) [x86_64-linux]
% for n in {98..90}
do
ruby -e 'n = ARGV.shift.to_i;
p n
Process.setrlimit(:NPROC, n)
pid = fork { p [:c, $$] }
p [:p, pid]
Process.wait pid
' $n
done
98
[:p, 24982]
[:c, 24982]
97
[:p, 24987]
[:c, 24987]
96
[:p, 24992]
[:c, 24992]
95
[:p, 24997]
[FATAL] Failed to create timer thread (errno: 11)
94
[FATAL] Failed to create timer thread (errno: 11)
[FATAL] Failed to create timer thread (errno: 11)
93
[FATAL] Failed to create timer thread (errno: 11)
92
[FATAL] Failed to create timer thread (errno: 11)
91
[FATAL] Failed to create timer thread (errno: 11)
90
[FATAL] Failed to create timer thread (errno: 11)

1.9 以降では、timer thread があるので、fork 直前には、プロセス内に main thread と timer thread のふたつがある。すべてがうまくいって子プロセスができると、子プロセス内にも main thread と timer thread のふたつができる。

とある理由により、親プロセスは fork system call を呼ぶ瞬間には timer thread を殺すので、まず親プロセスの timer thread が死んで、その後で子プロセスの main thread が生まれ、その後で親子両方で timer thread が生まれる。

結局 3つスレッドが生まれるので、(race condition を考慮しなければ) NPROC の値によって 4種類の挙動が観測できるはずで、そのとおりの結果になっている。

うまくいった場合:

96
[:p, 24992]
[:c, 24992]

子プロセスの main thread と親プロセスの timer thread は生まれなかったが、子プロセスの timer thread は作れなかった:

95
[:p, 24997]
[FATAL] Failed to create timer thread (errno: 11)

子プロセスの main thread は生まれたが、親子両方の timer thread は作れなかった:

94
[FATAL] Failed to create timer thread (errno: 11)
[FATAL] Failed to create timer thread (errno: 11)

子プロセスを作れなかった:

93
[FATAL] Failed to create timer thread (errno: 11)

[latest]


田中哲