# Buggy code
def _ssh_retry(func):
    """
    Decorator to retry ssh/scp/sftp in the case of a connection failure

    Will retry if:
    * an exception is caught
    * ssh returns 255
    Will not retry if
    * remaining_tries is <2
    * retries limit reached
    """

    @wraps(func)
    def wrapped(self, *args, **kwargs):
        remaining_tries = int(C.ANSIBLE_SSH_RETRIES) + 1
        cmd_summary = "%s..." % args[0]
        for attempt in range(remaining_tries):
            try:
                try:
                    return_tuple = func(self, *args, **kwargs)
                    display.vvv(return_tuple, host=self.host)
                    # 0 = success
                    # 1-254 = remote command return code
                    # 255 = failure from the ssh command itself
                except AnsibleControlPersistBrokenPipeError as e:
                    # Retry one more time because of the ControlPersist broken pipe (see #16731)
                    display.vvv("RETRYING BECAUSE OF CONTROLPERSIST BROKEN PIPE")
                    return_tuple = func(self, *args, **kwargs)

                if return_tuple[0] != 255:
                    break
                else:
                    raise AnsibleConnectionFailure(
                        "Failed to connect to the host via ssh: %s"
                        % to_native(return_tuple[2])
                    )
            except (AnsibleConnectionFailure, Exception) as e:
                if attempt == remaining_tries - 1:
                    raise
                else:
                    pause = 2**attempt - 1
                    if pause > 30:
                        pause = 30

                    if isinstance(e, AnsibleConnectionFailure):
                        msg = (
                            "ssh_retry: attempt: %d, ssh return code is 255. cmd (%s), pausing for %d seconds"
                            % (attempt, cmd_summary, pause)
                        )
                    else:
                        msg = (
                            "ssh_retry: attempt: %d, caught exception(%s) from cmd (%s), pausing for %d seconds"
                            % (attempt, e, cmd_summary, pause)
                        )

                    display.vv(msg, host=self.host)

                    time.sleep(pause)
                    continue

        return return_tuple

    return wrapped


# Traceback (OSError)
The full traceback is:
Traceback (most recent call last):
File "/Users/matt/projects/ansibledev/ansible/lib/ansible/executor/task_executor.py", line 125, in run
res = self._execute()
File "/Users/matt/projects/ansibledev/ansible/lib/ansible/executor/task_executor.py", line 526, in _execute
result = self._handler.run(task_vars=variables)
File "/Users/matt/projects/ansibledev/ansible/lib/ansible/plugins/action/normal.py", line 45, in run
results = merge_hash(results, self._execute_module(tmp=tmp, task_vars=task_vars, wrap_async=wrap_async))
File "/Users/matt/projects/ansibledev/ansible/lib/ansible/plugins/action/__init__.py", line 639, in _execute_module
tmp = self._make_tmp_path()
File "/Users/matt/projects/ansibledev/ansible/lib/ansible/plugins/action/__init__.py", line 245, in _make_tmp_path
tmpdir = self._remote_expand_user(self._play_context.remote_tmp_dir, sudoable=False)
File "/Users/matt/projects/ansibledev/ansible/lib/ansible/plugins/action/__init__.py", line 549, in _remote_expand_user
data = self._low_level_execute_command(cmd, sudoable=False)
File "/Users/matt/projects/ansibledev/ansible/lib/ansible/plugins/action/__init__.py", line 886, in _low_level_execute_command
rc, stdout, stderr = self._connection.exec_command(cmd, in_data=in_data, sudoable=sudoable)
File "/Users/matt/projects/ansibledev/ansible/lib/ansible/plugins/connection/ssh.py", line 920, in exec_command
(returncode, stdout, stderr) = self._run(cmd, in_data, sudoable=sudoable)
File "/Users/matt/projects/ansibledev/ansible/lib/ansible/plugins/connection/ssh.py", line 204, in wrapped
return_tuple = func(self, *args, **kwargs)
File "/Users/matt/projects/ansibledev/ansible/lib/ansible/plugins/connection/ssh.py", line 817, in _run
return self._bare_run(cmd, in_data, sudoable, checkrc)
File "/Users/matt/projects/ansibledev/ansible/lib/ansible/plugins/connection/ssh.py", line 584, in _bare_run
os.write(self.sshpass_pipe[1], to_bytes(self._play_context.password) + b'\n')
OSError: [Errno 9] Bad file descriptor

# Fixed code
def _ssh_retry(func):
    """
    Decorator to retry ssh/scp/sftp in the case of a connection failure

    Will retry if:
    * an exception is caught
    * ssh returns 255
    Will not retry if
    * remaining_tries is <2
    * retries limit reached
    """

    @wraps(func)
    def wrapped(self, *args, **kwargs):
        remaining_tries = int(C.ANSIBLE_SSH_RETRIES) + 1
        cmd_summary = "%s..." % args[0]
        for attempt in range(remaining_tries):
            cmd = args[0]
            if attempt != 0 and self._play_context.password and isinstance(cmd, list):
                # If this is a retry, the fd/pipe for sshpass is closed, and we need a new one
                self.sshpass_pipe = os.pipe()
                cmd[1] = b"-d" + to_bytes(
                    self.sshpass_pipe[0],
                    nonstring="simplerepr",
                    errors="surrogate_or_strict",
                )

            try:
                try:
                    return_tuple = func(self, *args, **kwargs)
                    display.vvv(return_tuple, host=self.host)
                    # 0 = success
                    # 1-254 = remote command return code
                    # 255 = failure from the ssh command itself
                except AnsibleControlPersistBrokenPipeError as e:
                    # Retry one more time because of the ControlPersist broken pipe (see #16731)
                    display.vvv("RETRYING BECAUSE OF CONTROLPERSIST BROKEN PIPE")
                    return_tuple = func(self, *args, **kwargs)

                if return_tuple[0] != 255:
                    break
                else:
                    raise AnsibleConnectionFailure(
                        "Failed to connect to the host via ssh: %s"
                        % to_native(return_tuple[2])
                    )
            except (AnsibleConnectionFailure, Exception) as e:
                if attempt == remaining_tries - 1:
                    raise
                else:
                    pause = 2**attempt - 1
                    if pause > 30:
                        pause = 30

                    if isinstance(e, AnsibleConnectionFailure):
                        msg = (
                            "ssh_retry: attempt: %d, ssh return code is 255. cmd (%s), pausing for %d seconds"
                            % (attempt, cmd_summary, pause)
                        )
                    else:
                        msg = (
                            "ssh_retry: attempt: %d, caught exception(%s) from cmd (%s), pausing for %d seconds"
                            % (attempt, e, cmd_summary, pause)
                        )

                    display.vv(msg, host=self.host)

                    time.sleep(pause)
                    continue

        return return_tuple

    return wrapped