prompt: 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()
  
  ```
  
golden_diff: 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)
  
verification_info: {"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"}]}