docs: def _determine_function_returning(self, func, all_funcs_completed=False):
          """
          Determine if a function returns or not.
  
          A function does not return if
          a) it is a SimProcedure that has NO_RET being True,
          or
          b) it is completely recovered (i.e. every block of this function has been recovered, and no future block will
             be added to it), and it does not have a ret or any equivalent instruction.
  
          A function returns if any of its block contains a ret instruction or any equivalence.
  
          :param Function func:   The function to work on.
          :param bool all_funcs_completed:    Whether we treat all functions as completed functions or not.
          :return:                True if the function returns, False if the function does not return, or None if it is
                                  not yet determinable with the information available at the moment.
          :rtype:                 bool or None
          """
  
          # If there is at least one return site, then this function is definitely returning
          if func.has_return:
              return True
  
          # Let's first see if it's a known SimProcedure that does not return
          if self.project.is_hooked(func.addr):
              procedure = self.project.hooked_by(func.addr)
          else:
              try:
                  procedure = self.project.simos.syscall_from_addr(func.addr, allow_unsupported=False)
              except AngrUnsupportedSyscallError:
                  procedure = None
  
          if procedure is not None and hasattr(procedure, 'NO_RET'):
              return not procedure.NO_RET
  
          # did we finish analyzing this function?
          if not all_funcs_completed and func.addr not in self._completed_functions:
              return None
  
          if not func.block_addrs_set:
              # there is no block inside this function
              # it might happen if the function has been incorrectly identified as part of another function
              # the error will be corrected during post-processing. In fact at this moment we cannot say anything
              # about whether this function returns or not. We always assume it returns.
              return True
  
          bail_out = False
  
          # if this function has jump-out sites or ret-out sites, it returns as long as any of the target function
          # returns
          for goout_site, type_ in [(site, 'jumpout') for site in func.jumpout_sites] + \
                                   [(site, 'retout') for site in func.retout_sites]:
  
              # determine where it jumps/returns to
              goout_site_successors = goout_site.successors()
              if not goout_site_successors:
                  # not sure where it jumps to. bail out
                  bail_out = True
                  continue
  
              # for ret-out sites, determine what function it calls
              if type_ == 'retout':
                  # see whether the function being called returns or not
                  func_successors = [succ for succ in goout_site_successors if isinstance(succ, Function)]
                  if func_successors and all(func_successor.returning in (None, False)
                                             for func_successor in func_successors):
                      # the returning of all possible function calls are undetermined, or they do not return
                      # ignore this site
                      continue
  
              if type_ == 'retout':
                  goout_target = next((succ for succ in goout_site_successors if not isinstance(succ, Function)), None)
              else:
                  goout_target = next((succ for succ in goout_site_successors), None)
              if goout_target is None:
                  # there is no jumpout site, which is weird, but what can we do...
                  continue
              if not self.kb.functions.contains_addr(goout_target.addr):
                  # wait it does not jump to a function?
                  bail_out = True
                  continue
  
              target_func = self.kb.functions[goout_target.addr]
              if target_func.returning is True:
                  return True
              elif target_func.returning is None:
                  # the returning status of at least one of the target functions is not decided yet.
                  bail_out = True
  
          if bail_out:
              # We cannot determine at this point. bail out
              return None
  
          # well this function does not return then
          return False