code: def join_or_die(self):
      
      if self._phase_desc.options.timeout_s is not None:
        self.join(self._phase_desc.options.timeout_s)
      else:
        self.join(DEFAULT_PHASE_TIMEOUT_S)
  
      # We got a return value or an exception and handled it.
      if isinstance(self._phase_execution_outcome, PhaseExecutionOutcome):
        return self._phase_execution_outcome
  
      # Check for timeout, indicated by None for
      # PhaseExecutionOutcome.phase_result.
      if self.is_alive():
        self.kill()
        return PhaseExecutionOutcome(None)
  
      # Phase was killed.
      return PhaseExecutionOutcome(threads.ThreadTerminationError())
docs: Wait for thread to finish, returning a PhaseExecutionOutcome instance.