# Buggy code
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


# 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 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