diff --git a/lib/ansible/executor/task_executor.py b/lib/ansible/executor/task_executor.py
index 734254a3051..8754f2cbc32 100644
--- a/lib/ansible/executor/task_executor.py
+++ b/lib/ansible/executor/task_executor.py
@@ -9,6 +9,7 @@ import pty
 import time
 import json
 import subprocess
+import sys
 import traceback
 
 from ansible import constants as C
@@ -855,7 +856,11 @@ class TaskExecutor:
         Starts the persistent connection
         '''
         master, slave = pty.openpty()
-        p = subprocess.Popen(["ansible-connection", to_text(os.getppid())], stdin=slave, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+
+        python = sys.executable
+        # Assume ansible-connection is in the same dir as sys.argv[0]
+        ansible_connection = os.path.join(os.path.dirname(sys.argv[0]), 'ansible-connection')
+        p = subprocess.Popen([python, ansible_connection, to_text(os.getppid())], stdin=slave, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
         stdin = os.fdopen(master, 'wb', 0)
         os.close(slave)
 
@@ -874,9 +879,12 @@ class TaskExecutor:
         stdin.close()
 
         if p.returncode == 0:
-            result = json.loads(to_text(stdout))
+            result = json.loads(to_text(stdout, errors='surrogate_then_replace'))
         else:
-            result = json.loads(to_text(stderr))
+            try:
+                result = json.loads(to_text(stderr, errors='surrogate_then_replace'))
+            except json.decoder.JSONDecodeError:
+                result = {'error': to_text(stderr, errors='surrogate_then_replace')}
 
         if 'messages' in result:
             for msg in result.get('messages'):
@@ -884,8 +892,9 @@ class TaskExecutor:
 
         if 'error' in result:
             if self._play_context.verbosity > 2:
-                msg = "The full traceback is:\n" + result['exception']
-                display.display(msg, color=C.COLOR_ERROR)
+                if result.get('exception'):
+                    msg = "The full traceback is:\n" + result['exception']
+                    display.display(msg, color=C.COLOR_ERROR)
             raise AnsibleError(result['error'])
 
         return result['socket_path']
diff --git a/lib/ansible/plugins/connection/persistent.py b/lib/ansible/plugins/connection/persistent.py
index 9a5f8827b56..16faf1a3e6c 100644
--- a/lib/ansible/plugins/connection/persistent.py
+++ b/lib/ansible/plugins/connection/persistent.py
@@ -17,6 +17,7 @@ import os
 import pty
 import json
 import subprocess
+import sys
 
 from ansible import constants as C
 from ansible.plugins.connection import ConnectionBase
@@ -75,7 +76,11 @@ class Connection(ConnectionBase):
         Starts the persistent connection
         '''
         master, slave = pty.openpty()
-        p = subprocess.Popen(["ansible-connection", to_text(os.getppid())], stdin=slave, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+
+        python = sys.executable
+        # Assume ansible-connection is in the same dir as sys.argv[0]
+        ansible_connection = os.path.join(os.path.dirname(sys.argv[0]), 'ansible-connection')
+        p = subprocess.Popen([python, ansible_connection, to_text(os.getppid())], stdin=slave, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
         stdin = os.fdopen(master, 'wb', 0)
         os.close(slave)
 
@@ -96,7 +101,10 @@ class Connection(ConnectionBase):
         if p.returncode == 0:
             result = json.loads(to_text(stdout, errors='surrogate_then_replace'))
         else:
-            result = json.loads(to_text(stderr, errors='surrogate_then_replace'))
+            try:
+                result = json.loads(to_text(stderr, errors='surrogate_then_replace'))
+            except json.decoder.JSONDecodeError:
+                result = {'error': to_text(stderr, errors='surrogate_then_replace')}
 
         if 'messages' in result:
             for msg in result.get('messages'):
@@ -104,8 +112,9 @@ class Connection(ConnectionBase):
 
         if 'error' in result:
             if self._play_context.verbosity > 2:
-                msg = "The full traceback is:\n" + result['exception']
-                display.display(msg, color=C.COLOR_ERROR)
+                if result.get('exception'):
+                    msg = "The full traceback is:\n" + result['exception']
+                    display.display(msg, color=C.COLOR_ERROR)
             raise AnsibleError(result['error'])
 
         return result['socket_path']