-
Notifications
You must be signed in to change notification settings - Fork 364
Fix resource leak in Daemon.run() #6249
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Signed-off-by: wangpeng <[email protected]>
WalkthroughThe change adds a finally block to the Estimated code review effort🎯 2 (Simple) | ⏱️ ~8 minutes
Pre-merge checks✅ Passed checks (3 passed)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (1)
avocado/utils/sysinfo.py (1)
236-255: Leak fix inDaemon.run()looks good; consider tightening resource handling aroundopen()andclose()The new
finallyblock correctly ensuresstdinandstdoutare closed even whensubprocess.Popen()raisesOSError, which fixes the reported FD leak.Two optional refinements you might consider while you’re here:
- Handle
open()failure without leaking: as written, ifstdout = open(logf_path, "w")fails afterstdinis opened,stdinwon’t be closed because the exception is raised before thetry/finally. Awithblock (or moving theopen()calls inside thetry) would cover that path as well.- Be resilient to
close()errors: ifstdin.close()orstdout.close()ever raisesOSError, it will now propagate out ofrun()and potentially mask the originalOSErrorfromPopen. Other parts of the codebase (for example,avocado/core/output.pypipe closing) ignoreOSErroron close, so you may want to wrap the closes in their owntry/except OSError: passfor consistency.For example, you could simplify and harden this section like:
- stdin = open(os.devnull, "r") # pylint: disable=W1514, R1732 - stdout = open(logf_path, "w") # pylint: disable=W1514, R1732 - - try: - # pylint: disable=R1732 - self.daemon_process = subprocess.Popen( - shlex.split(self.cmd), - stdin=stdin, - stdout=stdout, - stderr=subprocess.STDOUT, - shell=False, - env=env, - ) - except OSError as os_err: - raise CollectibleException( - f'Could not execute "{self.cmd}": ' f"{os_err}" - ) from os_err - finally: - stdin.close() - stdout.close() + try: + with open(os.devnull, "r") as stdin, open(logf_path, "w") as stdout: # pylint: disable=W1514 + # pylint: disable=R1732 + self.daemon_process = subprocess.Popen( + shlex.split(self.cmd), + stdin=stdin, + stdout=stdout, + stderr=subprocess.STDOUT, + shell=False, + env=env, + ) + except OSError as os_err: + raise CollectibleException( + f'Could not execute "{self.cmd}": ' f"{os_err}" + ) from os_errThis keeps the new behavior (no leaked FDs when
Popenfails), also closesstdinifstdoutfails to open, and lets the context manager handle closes cleanly.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
avocado/utils/sysinfo.py(1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
avocado/utils/sysinfo.py (2)
avocado/utils/iso9660.py (5)
close(171-176)close(200-206)close(298-300)close(349-360)close(454-460)avocado/core/output.py (3)
close(277-278)close(386-395)close(644-649)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (42)
- GitHub Check: rpm-build:centos-stream-9-x86_64
- GitHub Check: rpm-build:fedora-41-x86_64
- GitHub Check: rpm-build:fedora-41-s390x
- GitHub Check: rpm-build:fedora-rawhide-x86_64
- GitHub Check: rpm-build:fedora-41-aarch64
- GitHub Check: rpm-build:epel-9-x86_64
- GitHub Check: rpm-build:fedora-43-x86_64
- GitHub Check: rpm-build:fedora-42-x86_64
- GitHub Check: rpm-build:fedora-41-ppc64le
- GitHub Check: rpm-build:fedora-43-x86_64
- GitHub Check: rpm-build:fedora-41-x86_64
- GitHub Check: rpm-build:fedora-41-aarch64
- GitHub Check: rpm-build:fedora-rawhide-x86_64
- GitHub Check: rpm-build:centos-stream-9-x86_64
- GitHub Check: rpm-build:fedora-42-x86_64
- GitHub Check: rpm-build:fedora-41-s390x
- GitHub Check: rpm-build:epel-9-x86_64
- GitHub Check: rpm-build:fedora-41-ppc64le
- GitHub Check: Linux with Python 3.12
- GitHub Check: Linux with Python 3.13
- GitHub Check: Linux with Python 3.9
- GitHub Check: Linux with Python 3.10
- GitHub Check: Linux with Python 3.11
- GitHub Check: rpm-build:fedora-43-x86_64
- GitHub Check: rpm-build:fedora-rawhide-x86_64
- GitHub Check: rpm-build:fedora-41-ppc64le
- GitHub Check: rpm-build:fedora-41-aarch64
- GitHub Check: rpm-build:centos-stream-9-x86_64
- GitHub Check: rpm-build:epel-9-x86_64
- GitHub Check: rpm-build:fedora-42-x86_64
- GitHub Check: rpm-build:fedora-41-s390x
- GitHub Check: rpm-build:fedora-41-x86_64
- GitHub Check: Egg task debian:12.4
- GitHub Check: Podman spawner with 3rd party runner plugin
- GitHub Check: Version task ubuntu:22.04
- GitHub Check: Fedora selftests
- GitHub Check: Windows with Python 3.10
- GitHub Check: macOS with Python 3.11
- GitHub Check: Version task debian:12.4
- GitHub Check: Static checks
- GitHub Check: Version task ubi:8.8
- GitHub Check: Code Coverage (3.11)
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #6249 +/- ##
==========================================
- Coverage 73.48% 73.47% -0.02%
==========================================
Files 206 206
Lines 22494 22496 +2
==========================================
- Hits 16530 16529 -1
- Misses 5964 5967 +3 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
richtja
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @wangp-h, these changes LGTM and the CI failure are not related to this PR. Thank you.
Fix resource leak in
Daemon.run()whensubprocess.Popen()failsThe
Daemon.run()method opens file objects for stdin and stdout butdoesn't close them when
subprocess.Popen()raises an OSError. Thiscauses file descriptor leaks, especially problematic when commands
are misconfigured or don't exist.
Add a finally block to ensure file objects are always closed,
regardless of whether
Popen()succeeds or fails.Summary by CodeRabbit
✏️ Tip: You can customize this high-level summary in your review settings.