code: def test_normal_execution(self) -> None:
      with ipc.PIDServer(addr=0, num_clients=2) as pid_server:
          assert pid_server.listener
          _, port = pid_server.listener.getsockname()
  
          procs = [
              multiprocessing.Process(
                  target=TestPIDServer._worker_proc,
                  args=(port, True, 0.1, 5),
              ),
              multiprocessing.Process(
                  target=TestPIDServer._worker_proc,
                  args=(port, True, 0.1, 5),
              ),
          ]
  
          for p in procs:
              p.start()
  
          pid_server.run()
  
          for p in procs:
              p.join()
  
          assert len(pid_server.graceful_shutdowns) == 2
  
imports: import abc
  import itertools
  import multiprocessing
  import sys
  import textwrap
  import time
  import traceback
  from typing import Any, List, Optional, cast
  import pytest
  import determined
  from determined import core, ipc
  from tests import parallel
label_desc: Use image node_id 2 for calling the TestPIDServer obj's underlying member method code with example usage: obj.test_normal_execution() without return types