We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
exec_start does not return command output
I encountered this problem in my work and managed to write an isolated exposing test case attached to this issue.

This program works well on Linux Mint 18.3 and Docker version 17.05.0-ce, build 89658be
but fails on Centos 7.3 with Docker version 1.13.1, build b303bf6/1.13.1

I investigated this issue deeper and wrote an equivalent program using docker REST API and requests_unixsocket library. The program + strace shows that the body in the reply for REST endpoint associated to exec_start if interpreted in the wrong way.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `docker/utils/socket.py`
Content:
```
1 import errno
2 import os
3 import select
4 import struct
5 
6 import six
7 
8 try:
9     from ..transport import NpipeSocket
10 except ImportError:
11     NpipeSocket = type(None)
12 
13 
14 class SocketError(Exception):
15     pass
16 
17 
18 def read(socket, n=4096):
19     """
20     Reads at most n bytes from socket
21     """
22 
23     recoverable_errors = (errno.EINTR, errno.EDEADLK, errno.EWOULDBLOCK)
24 
25     # wait for data to become available
26     if not isinstance(socket, NpipeSocket):
27         select.select([socket], [], [])
28 
29     try:
30         if hasattr(socket, 'recv'):
31             return socket.recv(n)
32         return os.read(socket.fileno(), n)
33     except EnvironmentError as e:
34         if e.errno not in recoverable_errors:
35             raise
36 
37 
38 def read_exactly(socket, n):
39     """
40     Reads exactly n bytes from socket
41     Raises SocketError if there isn't enough data
42     """
43     data = six.binary_type()
44     while len(data) < n:
45         next_data = read(socket, n - len(data))
46         if not next_data:
47             raise SocketError("Unexpected EOF")
48         data += next_data
49     return data
50 
51 
52 def next_frame_size(socket):
53     """
54     Returns the size of the next frame of data waiting to be read from socket,
55     according to the protocol defined here:
56 
57     https://docs.docker.com/engine/reference/api/docker_remote_api_v1.24/#/attach-to-a-container
58     """
59     try:
60         data = read_exactly(socket, 8)
61     except SocketError:
62         return 0
63 
64     _, actual = struct.unpack('>BxxxL', data)
65     return actual
66 
67 
68 def frames_iter(socket):
69     """
70     Returns a generator of frames read from socket
71     """
72     while True:
73         n = next_frame_size(socket)
74         if n == 0:
75             break
76         while n > 0:
77             result = read(socket, n)
78             if result is None:
79                 continue
80             data_length = len(result)
81             if data_length == 0:
82                 # We have reached EOF
83                 return
84             n -= data_length
85             yield result
86 
87 
88 def socket_raw_iter(socket):
89     """
90     Returns a generator of data read from the socket.
91     This is used for non-multiplexed streams.
92     """
93     while True:
94         result = read(socket)
95         if len(result) == 0:
96             # We have reached EOF
97             return
98         yield result
99
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/docker/utils/socket.py b/docker/utils/socket.py
--- a/docker/utils/socket.py
+++ b/docker/utils/socket.py
@@ -59,7 +59,7 @@
     try:
         data = read_exactly(socket, 8)
     except SocketError:
-        return 0
+        return -1
 
     _, actual = struct.unpack('>BxxxL', data)
     return actual
@@ -71,7 +71,7 @@
     """
     while True:
         n = next_frame_size(socket)
-        if n == 0:
+        if n < 0:
             break
         while n > 0:
             result = read(socket, n)

{"golden_diff": "diff --git a/docker/utils/socket.py b/docker/utils/socket.py\n--- a/docker/utils/socket.py\n+++ b/docker/utils/socket.py\n@@ -59,7 +59,7 @@\n     try:\n         data = read_exactly(socket, 8)\n     except SocketError:\n-        return 0\n+        return -1\n \n     _, actual = struct.unpack('>BxxxL', data)\n     return actual\n@@ -71,7 +71,7 @@\n     \"\"\"\n     while True:\n         n = next_frame_size(socket)\n-        if n == 0:\n+        if n < 0:\n             break\n         while n > 0:\n             result = read(socket, n)\n", "issue": "exec_start does not return command output\nI encountered this problem in my work and managed to write an isolated exposing test case attached to this issue.\r\n\r\nThis program works well on Linux Mint 18.3 and Docker version 17.05.0-ce, build 89658be\r\nbut fails on Centos 7.3 with Docker version 1.13.1, build b303bf6/1.13.1\r\n\r\nI investigated this issue deeper and wrote an equivalent program using docker REST API and requests_unixsocket library. The program + strace shows that the body in the reply for REST endpoint associated to exec_start if interpreted in the wrong way.\n", "before_files": [{"content": "import errno\nimport os\nimport select\nimport struct\n\nimport six\n\ntry:\n    from ..transport import NpipeSocket\nexcept ImportError:\n    NpipeSocket = type(None)\n\n\nclass SocketError(Exception):\n    pass\n\n\ndef read(socket, n=4096):\n    \"\"\"\n    Reads at most n bytes from socket\n    \"\"\"\n\n    recoverable_errors = (errno.EINTR, errno.EDEADLK, errno.EWOULDBLOCK)\n\n    # wait for data to become available\n    if not isinstance(socket, NpipeSocket):\n        select.select([socket], [], [])\n\n    try:\n        if hasattr(socket, 'recv'):\n            return socket.recv(n)\n        return os.read(socket.fileno(), n)\n    except EnvironmentError as e:\n        if e.errno not in recoverable_errors:\n            raise\n\n\ndef read_exactly(socket, n):\n    \"\"\"\n    Reads exactly n bytes from socket\n    Raises SocketError if there isn't enough data\n    \"\"\"\n    data = six.binary_type()\n    while len(data) < n:\n        next_data = read(socket, n - len(data))\n        if not next_data:\n            raise SocketError(\"Unexpected EOF\")\n        data += next_data\n    return data\n\n\ndef next_frame_size(socket):\n    \"\"\"\n    Returns the size of the next frame of data waiting to be read from socket,\n    according to the protocol defined here:\n\n    https://docs.docker.com/engine/reference/api/docker_remote_api_v1.24/#/attach-to-a-container\n    \"\"\"\n    try:\n        data = read_exactly(socket, 8)\n    except SocketError:\n        return 0\n\n    _, actual = struct.unpack('>BxxxL', data)\n    return actual\n\n\ndef frames_iter(socket):\n    \"\"\"\n    Returns a generator of frames read from socket\n    \"\"\"\n    while True:\n        n = next_frame_size(socket)\n        if n == 0:\n            break\n        while n > 0:\n            result = read(socket, n)\n            if result is None:\n                continue\n            data_length = len(result)\n            if data_length == 0:\n                # We have reached EOF\n                return\n            n -= data_length\n            yield result\n\n\ndef socket_raw_iter(socket):\n    \"\"\"\n    Returns a generator of data read from the socket.\n    This is used for non-multiplexed streams.\n    \"\"\"\n    while True:\n        result = read(socket)\n        if len(result) == 0:\n            # We have reached EOF\n            return\n        yield result\n", "path": "docker/utils/socket.py"}], "after_files": [{"content": "import errno\nimport os\nimport select\nimport struct\n\nimport six\n\ntry:\n    from ..transport import NpipeSocket\nexcept ImportError:\n    NpipeSocket = type(None)\n\n\nclass SocketError(Exception):\n    pass\n\n\ndef read(socket, n=4096):\n    \"\"\"\n    Reads at most n bytes from socket\n    \"\"\"\n\n    recoverable_errors = (errno.EINTR, errno.EDEADLK, errno.EWOULDBLOCK)\n\n    # wait for data to become available\n    if not isinstance(socket, NpipeSocket):\n        select.select([socket], [], [])\n\n    try:\n        if hasattr(socket, 'recv'):\n            return socket.recv(n)\n        return os.read(socket.fileno(), n)\n    except EnvironmentError as e:\n        if e.errno not in recoverable_errors:\n            raise\n\n\ndef read_exactly(socket, n):\n    \"\"\"\n    Reads exactly n bytes from socket\n    Raises SocketError if there isn't enough data\n    \"\"\"\n    data = six.binary_type()\n    while len(data) < n:\n        next_data = read(socket, n - len(data))\n        if not next_data:\n            raise SocketError(\"Unexpected EOF\")\n        data += next_data\n    return data\n\n\ndef next_frame_size(socket):\n    \"\"\"\n    Returns the size of the next frame of data waiting to be read from socket,\n    according to the protocol defined here:\n\n    https://docs.docker.com/engine/reference/api/docker_remote_api_v1.24/#/attach-to-a-container\n    \"\"\"\n    try:\n        data = read_exactly(socket, 8)\n    except SocketError:\n        return -1\n\n    _, actual = struct.unpack('>BxxxL', data)\n    return actual\n\n\ndef frames_iter(socket):\n    \"\"\"\n    Returns a generator of frames read from socket\n    \"\"\"\n    while True:\n        n = next_frame_size(socket)\n        if n < 0:\n            break\n        while n > 0:\n            result = read(socket, n)\n            if result is None:\n                continue\n            data_length = len(result)\n            if data_length == 0:\n                # We have reached EOF\n                return\n            n -= data_length\n            yield result\n\n\ndef socket_raw_iter(socket):\n    \"\"\"\n    Returns a generator of data read from the socket.\n    This is used for non-multiplexed streams.\n    \"\"\"\n    while True:\n        result = read(socket)\n        if len(result) == 0:\n            # We have reached EOF\n            return\n        yield result\n", "path": "docker/utils/socket.py"}]}