MCPcopy Create free account
hub / github.com/pytest-dev/pytest / LsofFdLeakChecker

Class LsofFdLeakChecker

src/_pytest/pytester.py:124–186  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

122
123
124class LsofFdLeakChecker:
125 def get_open_files(self) -> List[Tuple[str, str]]:
126 out = subprocess.run(
127 ("lsof", "-Ffn0", "-p", str(os.getpid())),
128 stdout=subprocess.PIPE,
129 stderr=subprocess.DEVNULL,
130 check=True,
131 universal_newlines=True,
132 ).stdout
133
134 def isopen(line: str) -> bool:
135 return line.startswith("f") and (
136 "deleted" not in line
137 and "mem" not in line
138 and "txt" not in line
139 and "cwd" not in line
140 )
141
142 open_files = []
143
144 for line in out.split("\n"):
145 if isopen(line):
146 fields = line.split("\0")
147 fd = fields[0][1:]
148 filename = fields[1][1:]
149 if filename in IGNORE_PAM:
150 continue
151 if filename.startswith("/"):
152 open_files.append((fd, filename))
153
154 return open_files
155
156 def matching_platform(self) -> bool:
157 try:
158 subprocess.run(("lsof", "-v"), check=True)
159 except (OSError, subprocess.CalledProcessError):
160 return False
161 else:
162 return True
163
164 @hookimpl(hookwrapper=True, tryfirst=True)
165 def pytest_runtest_protocol(self, item: Item) -> Generator[None, None, None]:
166 lines1 = self.get_open_files()
167 yield
168 if hasattr(sys, "pypy_version_info"):
169 gc.collect()
170 lines2 = self.get_open_files()
171
172 new_fds = {t[0] for t in lines2} - {t[0] for t in lines1}
173 leaked_files = [t for t in lines2 if t[0] in new_fds]
174 if leaked_files:
175 error = [
176 "***** %s FD leakage detected" % len(leaked_files),
177 *(str(f) for f in leaked_files),
178 "*** Before:",
179 *(str(f) for f in lines1),
180 "*** After:",
181 *(str(f) for f in lines2),

Callers 1

pytest_configureFunction · 0.85

Calls

no outgoing calls

Tested by 1

pytest_configureFunction · 0.68