Support for Python 14 #3319

This commit is contained in:
nicolargo
2025-10-18 12:03:18 +02:00
parent a41a67edf7
commit f01008f430
2 changed files with 65 additions and 3 deletions

View File

@@ -17,6 +17,7 @@ import base64
import errno
import functools
import importlib
import multiprocessing
import os
import platform
import queue
@@ -27,7 +28,6 @@ import weakref
from collections import OrderedDict
from configparser import ConfigParser, NoOptionError, NoSectionError
from datetime import datetime
from multiprocessing import Process, Queue
from operator import itemgetter, methodcaller
from statistics import mean
from typing import Any, Optional, Union
@@ -97,6 +97,11 @@ viewkeys = methodcaller('keys')
viewvalues = methodcaller('values')
viewitems = methodcaller('items')
# Multiprocessing start method (on POSIX system)
if LINUX or BSD or SUNOS or MACOS:
ctx_mp_fork = multiprocessing.get_context('fork')
else:
ctx_mp_fork = multiprocessing.get_context()
###################
# GLOBALS FUNCTIONS
@@ -600,8 +605,8 @@ def exit_after(seconds, default=None):
return func
def wraps(*args, **kwargs):
q = Queue()
p = Process(target=handler, args=(q, func, args, kwargs))
q = ctx_mp_fork.Queue()
p = ctx_mp_fork.Process(target=handler, args=(q, func, args, kwargs))
p.start()
p.join(timeout=seconds)
if not p.is_alive():

View File

@@ -0,0 +1,57 @@
####################################################################################
#
# Migration of the code issue3290.py to use multiprocessing with 'fork' start method
#
####################################################################################
import multiprocessing
import time
import psutil
# multiprocessing.set_start_method("fork")
ctx_mp_fork = multiprocessing.get_context('fork')
def exit_after(seconds, default=None):
"""Exit the function if it takes more than 'second' seconds to complete.
In this case, return the value of 'default' (default: None)."""
def handler(q, func, args, kwargs):
q.put(func(*args, **kwargs))
def decorator(func):
def wraps(*args, **kwargs):
q = ctx_mp_fork.Queue()
p = ctx_mp_fork.Process(target=handler, args=(q, func, args, kwargs))
p.start()
p.join(timeout=seconds)
if not p.is_alive():
return q.get()
p.terminate()
p.join(timeout=0.1)
if p.is_alive():
# Kill in case processes doesn't terminate
# Happens with cases like broken NFS connections
p.kill()
return default
return wraps
return decorator
class Issue3290:
@exit_after(1, default=None)
def blocking_io_call(self, fs):
try:
return psutil.disk_usage(fs)
except OSError:
return None
issue = Issue3290()
while True:
print(f"{time.time()} {issue.blocking_io_call('/home/nicolargo/tmp/hang')}")
time.sleep(1)