### What do you see as an issue?

The documentation for zombie tasks https://airflow.apache.org/docs/apache-airflow/stable/core-concepts/tasks.html#zombie-undead-tasks is a bit abstract at the moment. There is a scope for enhancing the document by explaining how Airflow detects tasks as zombies

### Solving the problem

We can enhance the documentation by translating this query https://github.com/astronomer/airflow/blob/main/airflow/jobs/scheduler_job_runner.py#L1721 to a layman readable text in our documentation.

### Anything else

It might also help to add developer contribution steps to reproduce zombies locally.

### Are you willing to submit PR?

- [ ] Yes I am willing to submit a PR!

### Code of Conduct

- [X] I agree to follow this project's [Code of Conduct](https://github.com/apache/airflow/blob/main/CODE_OF_CONDUCT.md)

callback_to_execute = DagCallbackRequest(
                full_filepath=dag.fileloc,
                dag_id=dag.dag_id,
                run_id=dag_run.run_id,
                is_failure_callback=True,
                processor_subdir=dag_model.processor_subdir,
                msg="timed_out",
            )
            dag_run.notify_dagrun_state_changed()
            duration = dag_run.end_date - dag_run.start_date
            Stats.timing(f"dagrun.duration.failed.{dag_run.dag_id}", duration)
            Stats.timing("dagrun.duration.failed", duration, tags={"dag_id": dag_run.dag_id})
            return callback_to_execute
        if dag_run.execution_date > timezone.utcnow() and not dag.allow_future_exec_dates:
            self.log.error("Execution date is in future: %s", dag_run.execution_date)
            return callback
        if not self._verify_integrity_if_dag_changed(dag_run=dag_run, session=session):
            self.log.warning("The DAG disappeared before verifying integrity: %s. Skipping.", dag_run.dag_id)
            return callback
        
        schedulable_tis, callback_to_run = dag_run.update_state(session=session, execute_callbacks=False)
        if self._should_update_dag_next_dagruns(dag, dag_model, last_dag_run=dag_run, session=session):
            dag_model.calculate_dagrun_date_fields(dag, dag.get_run_data_interval(dag_run))
        
        
        
        
        dag_run.schedule_tis(schedulable_tis, session, max_tis_per_query=self.job.max_tis_per_query)
        return callback_to_run
    def _verify_integrity_if_dag_changed(self, dag_run: DagRun, session: Session) -> bool: