From 47cb9f7b63f8477f637a0c93ca65a24b25c2effd Mon Sep 17 00:00:00 2001 From: "James E. Blair" Date: Sat, 22 Feb 2025 09:52:54 -0800 Subject: [PATCH] Improve nodescan worker cleanup Rather than relying on __del__ to close the pipe fds, let's use the join() method which we should be calling during our shutdown procedure anyway. This will ensure the pipes are closed even if the object is not GC'd. Also, remove the backref from the request to the worker to increase the chances that the object can be GC'd. Change-Id: I71eb34b2502adebe7b3bf32eefb0fa540535f8f7 --- zuul/launcher/server.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/zuul/launcher/server.py b/zuul/launcher/server.py index 1cfe69e508..e5e00a9fee 100644 --- a/zuul/launcher/server.py +++ b/zuul/launcher/server.py @@ -327,6 +327,7 @@ class NodescanRequest: self.key_connection_failures, self.key_negotiation_failures, dt) + self.worker = None def result(self): """Return the resulting keys, or raise an exception""" @@ -553,8 +554,7 @@ class NodescanWorker: MAX_REQUESTS = 100 def __init__(self): - # Remember to close all pipes on __del__ to prevent leaks in - # tests. + # Remember to close all pipes to prevent leaks in tests. self.wake_read, self.wake_write = os.pipe() fcntl.fcntl(self.wake_read, fcntl.F_SETFL, os.O_NONBLOCK) self._running = False @@ -563,10 +563,6 @@ class NodescanWorker: self.poll = select.epoll() self.poll.register(self.wake_read, select.EPOLLIN) - def __del__(self): - os.close(self.wake_read) - os.close(self.wake_write) - def start(self): self._running = True self.thread = threading.Thread(target=self.run, daemon=True) @@ -578,6 +574,8 @@ class NodescanWorker: def join(self): self.thread.join() + os.close(self.wake_read) + os.close(self.wake_write) def addRequest(self, request): """Submit a nodescan request"""