MathPython
23 May 2020

Python の ThreadPoolExecutor は max_workers を適切に指定しないとゾンビのプロセスが生まれるかもしれない

注意:この記事は情報に誤りがあるかもしれない

Python の ThreadPoolExecutor は基本的に with 内で動かすが、実際のスレッド数を超える値を max_workers に指定すると予想外のことが起きる。

例えば 3 つのプロセスを並列化したいとき、max_workers を 4 にすると、4 - 3 = 1 のゾンビ・プロセスが生まれる。全体のプログラムがデーモン化されている場合、この 1 個のスレッドが with で回収されない。

例えば gunicorn で動かす Django または Flask のプログラム内に ThreadPoolExecutor で並列化した関数があるとする。この ThreadPoolExecutor で max_workers を関数の数よりも多く設定していると

となる。これらのゾンビ・デーモンはシグナルで強制終了されない限り消えない。

デーモンになっていないプログラム、例えばローカルで動かしている Flask では max_workers の値にかかわらず、余ったスレッドは with で消される(たぶん)。

また ThreadPoolExecutor は OS に依存するため、実際は Pebble などを使う。Python の並列化でシグナルを直接扱っているソースコードをよく見かけるが、たぶん避けたほうがいい。