mirror of
https://github.com/microsoft/debugpy.git
synced 2025-12-23 08:48:12 +00:00
(fixes #208) Currently when ptvsd starts up (as server) it listens for a connection and shuts down when the debug session is done. This prevents re-attach. To fix this we go back to listening for a connection after getting a "disconnect" (or the client closes the connection).
103 lines
2.7 KiB
Python
103 lines
2.7 KiB
Python
import subprocess
|
|
import sys
|
|
|
|
from . import Closeable
|
|
|
|
|
|
class Proc(Closeable):
|
|
"""A wrapper around a subprocess.Popen object."""
|
|
|
|
VERBOSE = False
|
|
#VERBOSE = True
|
|
|
|
@classmethod
|
|
def start_python_script(cls, filename, argv, **kwargs):
|
|
argv = [
|
|
sys.executable,
|
|
filename,
|
|
] + argv
|
|
return cls.start(argv, **kwargs)
|
|
|
|
@classmethod
|
|
def start_python_module(cls, module, argv, **kwargs):
|
|
argv = [
|
|
sys.executable,
|
|
'-m', module,
|
|
] + argv
|
|
return cls.start(argv, **kwargs)
|
|
|
|
@classmethod
|
|
def start(cls, argv, env=None, stdout=None, stderr=None):
|
|
if env is None:
|
|
env = {}
|
|
if cls.VERBOSE:
|
|
env.setdefault('PTVSD_DEBUG', '1')
|
|
proc = cls._start(argv, env, stdout, stderr)
|
|
return cls(proc, owned=True)
|
|
|
|
@classmethod
|
|
def _start(cls, argv, env, stdout, stderr):
|
|
if stdout is None:
|
|
stdout = subprocess.PIPE
|
|
if stderr is None:
|
|
stderr = subprocess.STDOUT
|
|
proc = subprocess.Popen(
|
|
argv,
|
|
stdout=stdout,
|
|
stderr=stderr,
|
|
env=env,
|
|
)
|
|
return proc
|
|
|
|
def __init__(self, proc, owned=False):
|
|
super(Proc, self).__init__()
|
|
assert isinstance(proc, subprocess.Popen)
|
|
self._proc = proc
|
|
if proc.stdout is sys.stdout or proc.stdout is None:
|
|
self._output = None
|
|
|
|
# TODO: Emulate class-only methods?
|
|
#def __getattribute__(self, name):
|
|
# val = super(Proc, self).__getattribute__(name)
|
|
# if isinstance(type(self).__dict__.get(name), classmethod):
|
|
# raise AttributeError(name)
|
|
# return val
|
|
|
|
@property
|
|
def pid(self):
|
|
return self._proc.pid
|
|
|
|
@property
|
|
def output(self):
|
|
try:
|
|
# TODO: Could there be more?
|
|
return self._output
|
|
except AttributeError:
|
|
# TODO: Wait until proc done? (piped output blocks)
|
|
self._output = self._proc.stdout.read()
|
|
return self._output
|
|
|
|
@property
|
|
def exitcode(self):
|
|
return self._proc.returncode
|
|
|
|
def wait(self):
|
|
self._proc.wait()
|
|
|
|
# internal methods
|
|
|
|
def _close(self):
|
|
if self._proc is not None:
|
|
try:
|
|
self._proc.kill()
|
|
except OSError:
|
|
# Already killed.
|
|
pass
|
|
else:
|
|
if self.VERBOSE:
|
|
print('proc killed')
|
|
if self.VERBOSE:
|
|
out = self.output
|
|
if out is not None:
|
|
lines = out.decode('utf-8').splitlines()
|
|
print(' + ' + '\n + '.join(lines))
|