Diagnose which processes might be holding a port.
(port_name: str)
| 164 | |
| 165 | |
| 166 | def diagnose_port(port_name: str) -> None: |
| 167 | """Diagnose which processes might be holding a port.""" |
| 168 | print("=" * 80) |
| 169 | print(f"Port Lock Diagnostic: {port_name}") |
| 170 | print("=" * 80) |
| 171 | print() |
| 172 | |
| 173 | # Step 1: Try to identify processes with the port open as a file handle |
| 174 | print("[1] Processes with open file handles matching port name:") |
| 175 | print("-" * 80) |
| 176 | processes_with_files = find_processes_with_open_files(port_name) |
| 177 | |
| 178 | if processes_with_files: |
| 179 | for proc, files in processes_with_files: |
| 180 | try: |
| 181 | proc_info = cast( |
| 182 | dict[str, Any], |
| 183 | proc.as_dict(attrs=["pid", "name", "cmdline"]), # type: ignore[misc] |
| 184 | ) |
| 185 | print(f" PID {proc_info['pid']}: {proc_info['name']}") |
| 186 | print(f" Command: {format_cmdline(proc_info['cmdline'])}") |
| 187 | print(f" Open files: {', '.join(files)}") |
| 188 | |
| 189 | # Check if it matches kill patterns |
| 190 | matches, patterns = check_matches_kill_patterns( |
| 191 | proc_info["name"], proc_info["cmdline"], port_name |
| 192 | ) |
| 193 | if matches: |
| 194 | print(f" ✅ Would be killed by: {', '.join(patterns)}") |
| 195 | else: |
| 196 | print(" ❌ NOT matched by any kill pattern") |
| 197 | print() |
| 198 | except (psutil.NoSuchProcess, psutil.AccessDenied): |
| 199 | pass |
| 200 | else: |
| 201 | print(" No processes found with open file handles matching port name") |
| 202 | print(" (This is expected on Windows - COM ports may not show as open files)") |
| 203 | print() |
| 204 | |
| 205 | # Step 2: List all processes that match kill patterns |
| 206 | print("[2] All processes matching debug_attached.py kill patterns:") |
| 207 | print("-" * 80) |
| 208 | |
| 209 | found_any = False |
| 210 | for proc in psutil.process_iter(["pid", "name", "cmdline", "ppid"]): |
| 211 | try: |
| 212 | proc_info = cast( |
| 213 | dict[str, Any], |
| 214 | proc.as_dict(attrs=["pid", "name", "cmdline", "ppid"]), # type: ignore[misc] |
| 215 | ) |
| 216 | matches, patterns = check_matches_kill_patterns( |
| 217 | proc_info["name"], proc_info["cmdline"], port_name |
| 218 | ) |
| 219 | |
| 220 | if matches: |
| 221 | found_any = True |
| 222 | print( |
| 223 | f" PID {proc_info['pid']}: {proc_info['name']} (Parent: {proc_info['ppid']})" |
no test coverage detected