summaryrefslogtreecommitdiff
path: root/searx
diff options
context:
space:
mode:
authorMarkus Heiser <markus.heiser@darmarIT.de>2025-07-08 09:30:41 +0200
committerGitHub <noreply@github.com>2025-07-08 09:30:41 +0200
commitfe52290e653e969c959b3160c1a09f02e751efd2 (patch)
treef06623fd9e8e1022798cfd2fa481662f8847dcdb /searx
parent6ff40356352e9f5b9c7f9c5d58ac2fc787455036 (diff)
[fix] calculator plugin: subrocess is not closed on timeout (#4983)
The issue was introduced in commit: edfbf1e Problematic code:: def timeout_func(timeout, func, *args, **kwargs): ... if not p.is_alive(): ret_val = que.get() else: logger.debug("terminate function after timeout is exceeded") # type: ignore p.terminate() p.join() p.close() The `logger` function in the `else` path is not defined. Was accidentally removed in commit edfbf1e without providing an appropriate replacement.:: File "/usr/local/searxng/searx/plugins/calculator.py", line 216, in timeout_func logger.debug("terminate function after timeout is exceeded") # type: ignore ^^^^^^ NameError: name 'logger' is not defined The exception triggered by this prevents the `p.terminate()` from being executed. As a result, the processes accumulate in memory (memory leak). Related: https://github.com/searxng/searx-instances/discussions/708#discussioncomment-13688168 Signed-off-by: Markus Heiser <markus.heiser@darmarit.de>
Diffstat (limited to 'searx')
-rw-r--r--searx/plugins/calculator.py36
1 files changed, 17 insertions, 19 deletions
diff --git a/searx/plugins/calculator.py b/searx/plugins/calculator.py
index af44eea1e..5adaaaf22 100644
--- a/searx/plugins/calculator.py
+++ b/searx/plugins/calculator.py
@@ -40,6 +40,22 @@ class SXNGPlugin(Plugin):
preference_section="general",
)
+ def timeout_func(self, timeout, func, *args, **kwargs):
+ que = mp_fork.Queue()
+ p = mp_fork.Process(target=handler, args=(que, func, args), kwargs=kwargs)
+ p.start()
+ p.join(timeout=timeout)
+ ret_val = None
+ # pylint: disable=used-before-assignment,undefined-variable
+ if not p.is_alive():
+ ret_val = que.get()
+ else:
+ self.log.debug("terminate function (%s: %s // %s) after timeout is exceeded", func.__name__, args, kwargs)
+ p.terminate()
+ p.join()
+ p.close()
+ return ret_val
+
def post_search(self, request: "SXNG_Request", search: "SearchWithPlugins") -> EngineResults:
results = EngineResults()
@@ -72,7 +88,7 @@ class SXNGPlugin(Plugin):
query_py_formatted = query.replace("^", "**")
# Prevent the runtime from being longer than 50 ms
- res = timeout_func(0.05, _eval_expr, query_py_formatted)
+ res = self.timeout_func(0.05, _eval_expr, query_py_formatted)
if res is None or res[0] == "":
return results
@@ -200,21 +216,3 @@ def handler(q: multiprocessing.Queue, func, args, **kwargs): # pylint:disable=i
except:
q.put(None)
raise
-
-
-def timeout_func(timeout, func, *args, **kwargs):
-
- que = mp_fork.Queue()
- p = mp_fork.Process(target=handler, args=(que, func, args), kwargs=kwargs)
- p.start()
- p.join(timeout=timeout)
- ret_val = None
- # pylint: disable=used-before-assignment,undefined-variable
- if not p.is_alive():
- ret_val = que.get()
- else:
- logger.debug("terminate function after timeout is exceeded") # type: ignore
- p.terminate()
- p.join()
- p.close()
- return ret_val