Context manager for subprocess lifecycle management. Ensures process is properly terminated and cleaned up even on exceptions. Uses graceful termination first, then forceful kill if needed.
(args, timeout=SHORT_TIMEOUT)
| 165 | |
| 166 | @contextmanager |
| 167 | def _managed_subprocess(args, timeout=SHORT_TIMEOUT): |
| 168 | """ |
| 169 | Context manager for subprocess lifecycle management. |
| 170 | |
| 171 | Ensures process is properly terminated and cleaned up even on exceptions. |
| 172 | Uses graceful termination first, then forceful kill if needed. |
| 173 | """ |
| 174 | p = subprocess.Popen(args) |
| 175 | try: |
| 176 | yield p |
| 177 | finally: |
| 178 | try: |
| 179 | p.terminate() |
| 180 | try: |
| 181 | p.wait(timeout=timeout) |
| 182 | except subprocess.TimeoutExpired: |
| 183 | p.kill() |
| 184 | try: |
| 185 | p.wait(timeout=timeout) |
| 186 | except subprocess.TimeoutExpired: |
| 187 | pass # Process refuses to die, nothing more we can do |
| 188 | except OSError: |
| 189 | pass # Process already dead |
| 190 | |
| 191 | |
| 192 | def _cleanup_sockets(*sockets): |
no test coverage detected
searching dependent graphs…