8

マルチプロセスとマルチスレッドについて調べていると、デッドロックの危険があるので混在させるのはfork()後即exec()させる場合を除いて厳禁といった趣旨の記事がいくつか見当たりました。

記事の理屈はよくわかるのですが、これはPythonのthreading.Threadmultiprocessing.Processの場合でも同様なのでしょうか?


[Kenji Noguchiさんのコメントを受けての追記]
下記のテストコードを試してみました。

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import time from multiprocessing import Process

def other_proc_func(name): while True: time.sleep(1)

print('Hello {}'.format(name))

if name == 'main': for i in range(10): name = 'Proc{}'.format(i) p = Process(target=other_proc_func, args=[name]) p.deamon = True p.start()

while True:
    pass

この時、print('Hello {}'.format(__name__))はプロセスを生成した回数分呼び出されました(__name__ == '__main__'なのは初めの一回のみ)。別のモジュールからプロセスを生成した場合でも、トップレベルのモジュールから再実行が行われていました。
Python側がProcess.targetの関数を呼び出す際に、fork()でプロセスのコピーを行った後に、exec()でPythonを再実行しているように見えます。

これは参考文献にある、"意訳: fork()してライブラリ関数を呼び出さずにexec()すればOK"というケースに該当しそうに思うのですが、どうなのでしょうか?Pythonのソースコードを当たるべきかもしれませんが。

cubick
  • 20,987
  • 5
  • 25
  • 64
user3270390
  • 1,088
  • 3
  • 17
  • 34
  • Pythonでもデッドロックは起きますね。forkしてからスレッドを作れば安全な気もしますが...。 – Kenji Noguchi Jun 23 '17 at 04:22
  • http://www.evanjones.ca/fork-is-dangerous.html によれば、Pythonでもクラッシュを引き起こせるとありますね。この記事ではマルチプロセスとマルチスレッドではなく、親プロセスでsqlite3を使ってos.fork()で生成した子プロセスでurllib2を使った、という例のようですね。 – Toshihiro Kamiya Jun 24 '17 at 11:53
  • straceで調べてみました。fork()でプロセスのコピーを行った後に、exec()でPythonを再実行しているように見えます。⇒私の環境では、fork()していません。clone()を使っています。exec()も呼ばれていませんでした。その代わりソースファイルをreadし直していました。システムコールのfork/execでPythonの振る舞いを類推するのは危険な気がしてきました。 – akira ejiri Nov 14 '19 at 06:29

0 Answers0