From b14b2d0409cab0a828b76a026b1d9ee40dbc4008 Mon Sep 17 00:00:00 2001 From: Itamar Turner-Trauring Date: Mon, 20 Feb 2023 12:01:14 -0500 Subject: [PATCH] Use a nicer shutdown mechanism. --- src/allmydata/util/cputhreadpool.py | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/allmydata/util/cputhreadpool.py b/src/allmydata/util/cputhreadpool.py index a7f9d8bd6..a7407804a 100644 --- a/src/allmydata/util/cputhreadpool.py +++ b/src/allmydata/util/cputhreadpool.py @@ -17,6 +17,7 @@ scheduler affinity or cgroups, but that's not the end of the world. import os from typing import TypeVar, Callable, cast from functools import partial +import threading from twisted.python.threadpool import ThreadPool from twisted.internet.defer import Deferred @@ -25,8 +26,19 @@ from twisted.internet.interfaces import IReactorFromThreads _CPU_THREAD_POOL = ThreadPool(minthreads=0, maxthreads=os.cpu_count(), name="TahoeCPU") -# Daemon threads allow shutdown to happen: -_CPU_THREAD_POOL.threadFactory = partial(_CPU_THREAD_POOL.threadFactory, daemon=True) +if hasattr(threading, "_register_atexit"): + # This is a private API present in Python 3.8 or later, specifically + # designed for thread pool shutdown. Since it's private, it might go away + # at any point, so if it doesn't exist we still have a solution. + threading._register_atexit(_CPU_THREAD_POOL.stop) +else: + # Daemon threads allow shutdown to happen without any explicit stopping of + # threads. There are some bugs in old Python versions related to daemon + # threads (fixed in subsequent CPython patch releases), but Python's own + # thread pools use daemon threads in those versions so we're no worse off. + _CPU_THREAD_POOL.threadFactory = partial( + _CPU_THREAD_POOL.threadFactory, daemon=True + ) _CPU_THREAD_POOL.start()