docs: def _run_task(self, play, task, is_handler):
          ''' run a single task in the playbook and recursively run any subtasks.  '''
  
          self.callbacks.on_task_start(utils.template(play.basedir, task.name, task.module_vars, lookup_fatal=False), is_handler)
  
          # load up an appropriate ansible runner to run the task in parallel
          results = self._run_task_internal(task)
  
          # if no hosts are matched, carry on
          hosts_remaining = True
          if results is None:
              hosts_remaining = False
              results = {}
   
          contacted = results.get('contacted', {})
          self.stats.compute(results, ignore_errors=task.ignore_errors)
  
          # add facts to the global setup cache
          for host, result in contacted.iteritems():
              # Skip register variable if host is skipped
              if result.get('skipped', False):
                  continue
              facts = result.get('ansible_facts', {})
              self.SETUP_CACHE[host].update(facts)
              # extra vars need to always trump - so update  again following the facts
              self.SETUP_CACHE[host].update(self.extra_vars)
              if task.register:
                  if 'stdout' in result:
                      result['stdout_lines'] = result['stdout'].splitlines()
                  self.SETUP_CACHE[host][task.register] = result
  
          # flag which notify handlers need to be run
          if len(task.notify) > 0:
              for host, results in results.get('contacted',{}).iteritems():
                  if results.get('changed', False):
                      for handler_name in task.notify:
                          self._flag_handler(play, utils.template(play.basedir, handler_name, task.module_vars), host)
  
          return hosts_remaining