Repository: microsoft/ptvsd

Issue:
pydevd should report parent process ID in "initialize" response
This is mostly to allow us constructing a proper process tree inside the adapter. With the current proposed design, we know that an incoming server->adapter connection is a subprocess, if it's not the first such connection - the root process is always the first, and everything else is its subprocess. The access tokens ensure that there are no spurious connections.

However, in the case where you have child processes spawning other child processes, we don't have any way to determine that relationship. 


Discussion:
This should probably use `pydevdSystemInfo` to contain the additional field for ppid.

Resolving patch:
diff --git a/src/ptvsd/_vendored/pydevd/_pydevd_bundle/_debug_adapter/pydevd_schema.py b/src/ptvsd/_vendored/pydevd/_pydevd_bundle/_debug_adapter/pydevd_schema.py
--- a/src/ptvsd/_vendored/pydevd/_pydevd_bundle/_debug_adapter/pydevd_schema.py
+++ b/src/ptvsd/_vendored/pydevd/_pydevd_bundle/_debug_adapter/pydevd_schema.py
@@ -13921,6 +13921,10 @@ class PydevdProcessInfo(BaseSchema):
             "type": "integer",
             "description": "Process ID for the current process."
         },
+        "ppid": {
+            "type": "integer",
+            "description": "Parent Process ID for the current process."
+        },
         "executable": {
             "type": "string",
             "description": "Path to the executable as returned by 'sys.executable'."
@@ -13934,13 +13938,15 @@ class PydevdProcessInfo(BaseSchema):
 
     __slots__ = list(__props__.keys()) + ['kwargs']
 
-    def __init__(self, pid=None, executable=None, bitness=None, update_ids_from_dap=False, **kwargs):  # noqa (update_ids_from_dap may be unused)
+    def __init__(self, pid=None, ppid=None, executable=None, bitness=None, update_ids_from_dap=False, **kwargs):  # noqa (update_ids_from_dap may be unused)
         """
         :param integer pid: Process ID for the current process.
+        :param integer ppid: Parent Process ID for the current process.
         :param string executable: Path to the executable as returned by 'sys.executable'.
         :param integer bitness: Integer value indicating the bitness of the current process.
         """
         self.pid = pid
+        self.ppid = ppid
         self.executable = executable
         self.bitness = bitness
         self.kwargs = kwargs
@@ -13948,12 +13954,15 @@ def __init__(self, pid=None, executable=None, bitness=None, update_ids_from_dap=
 
     def to_dict(self, update_ids_to_dap=False):  # noqa (update_ids_to_dap may be unused)
         pid = self.pid
+        ppid = self.ppid
         executable = self.executable
         bitness = self.bitness
         dct = {
         }
         if pid is not None:
             dct['pid'] = pid
+        if ppid is not None:
+            dct['ppid'] = ppid
         if executable is not None:
             dct['executable'] = executable
         if bitness is not None:
diff --git a/src/ptvsd/_vendored/pydevd/_pydevd_bundle/pydevd_process_net_command_json.py b/src/ptvsd/_vendored/pydevd/_pydevd_bundle/pydevd_process_net_command_json.py
--- a/src/ptvsd/_vendored/pydevd/_pydevd_bundle/pydevd_process_net_command_json.py
+++ b/src/ptvsd/_vendored/pydevd/_pydevd_bundle/pydevd_process_net_command_json.py
@@ -962,6 +962,11 @@ def on_pydevdsysteminfo_request(self, py_db, request):
         except AttributeError:
             pid = None
 
+        try:
+            ppid = os.getppid()
+        except AttributeError:
+            ppid = None
+
         try:
             impl_desc = platform.python_implementation()
         except AttributeError:
@@ -978,6 +983,7 @@ def on_pydevdsysteminfo_request(self, py_db, request):
         platform_info = pydevd_schema.PydevdPlatformInfo(name=sys.platform)
         process_info = pydevd_schema.PydevdProcessInfo(
             pid=pid,
+            ppid=ppid,
             executable=sys.executable,
             bitness=64 if IS_64BIT_PROCESS else 32,
         )


Test patch:
diff --git a/src/ptvsd/_vendored/pydevd/tests_python/test_debugger_json.py b/src/ptvsd/_vendored/pydevd/tests_python/test_debugger_json.py
--- a/src/ptvsd/_vendored/pydevd/tests_python/test_debugger_json.py
+++ b/src/ptvsd/_vendored/pydevd/tests_python/test_debugger_json.py
@@ -2868,6 +2868,7 @@ def test_pydevd_systeminfo(case_setup):
         assert body['platform'] == {'name': sys.platform}
 
         assert 'pid' in body['process']
+        assert 'ppid' in body['process']
         assert body['process']['executable'] == sys.executable
         assert body['process']['bitness'] == 64 if IS_64BIT_PROCESS else 32