##### SUMMARY
If `callback_whitelist` contains a FQCN that does not exist, Ansible will crash:
```
ERROR! Unexpected Exception, this is probably a bug: 'NoneType' object has no attribute 'set_options'
the full traceback was:

Traceback (most recent call last):
  File "ansible/bin/ansible-playbook", line 123, in <module>
    exit_code = cli.run()
  File "ansible/lib/ansible/cli/playbook.py", line 127, in run
    results = pbex.run()
  File "ansible/lib/ansible/executor/playbook_executor.py", line 99, in run
    self._tqm.load_callbacks()
  File "ansible/lib/ansible/executor/task_queue_manager.py", line 165, in load_callbacks
    callback_obj.set_options()
AttributeError: 'NoneType' object has no attribute 'set_options'
```
This happens since #66128 (unsurprisingly). This is easy to fix by changing line 165 to
```
            if callback_obj is not None:
                callback_obj.set_options()
```
but this only fixes the symptom (crash), not the cause (no handling when callback not found).

I guess a better behavior would be to:
```
            if callback_obj is None:
                raise AnsibleError("Cannot find callback: %s" % callback_plugin_name)
```
or at least print a warning. Since I'm not sure what the correct behavior is, I'm creating this issue.

##### ISSUE TYPE
- Bug Report

##### COMPONENT NAME
lib/ansible/executor/task_queue_manager.py

##### ANSIBLE VERSION
```paste below
2.9
devel
```

self._start_at_done = True
        
        play_return = strategy.run(iterator, play_context)
        
        for host_name in iterator.get_failed_hosts():
            self._failed_hosts[host_name] = True
        strategy.cleanup()
        self._cleanup_processes()
        return play_return
    def cleanup(self):
        display.debug("RUNNING CLEANUP")
        self.terminate()
        self._final_q.close()
        self._cleanup_processes()
    def _cleanup_processes(self):
        if hasattr(self, '_workers'):
            for attempts_remaining in range(C.WORKER_SHUTDOWN_POLL_COUNT - 1, -1, -1):
                if not any(worker_prc and worker_prc.is_alive() for worker_prc in self._workers):
                    break
                if attempts_remaining:
                    time.sleep(C.WORKER_SHUTDOWN_POLL_DELAY)
                else:
                    display.warning('One or more worker processes are still running and will be terminated.')
            for worker_prc in self._workers:
                if worker_prc and worker_prc.is_alive():
                    try:
                        worker_prc.terminate()
                    except AttributeError:
                        pass
    def clear_failed_hosts(self):