From 9b99a8495ab3f56a62a6907e4211e24386ab60fc Mon Sep 17 00:00:00 2001 From: Alexander Koshevoy Date: Thu, 22 Oct 2020 23:36:28 +0300 Subject: [PATCH 1/6] Fix "docker-java-stream" thread stuck at UnixDomainSocket.recv() (OkHttp transport) (#1475) Prevent unnecessary recurring calls of `recv()` on UNIX socket, which sometimes results in blocking read and causes hanging of "docker-java-stream" thread. --- .../dockerjava/okhttp/UnixDomainSocket.java | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/docker-java-transport-okhttp/src/main/java/com/github/dockerjava/okhttp/UnixDomainSocket.java b/docker-java-transport-okhttp/src/main/java/com/github/dockerjava/okhttp/UnixDomainSocket.java index e2f1002d7..04cfe6063 100644 --- a/docker-java-transport-okhttp/src/main/java/com/github/dockerjava/okhttp/UnixDomainSocket.java +++ b/docker-java-transport-okhttp/src/main/java/com/github/dockerjava/okhttp/UnixDomainSocket.java @@ -232,20 +232,12 @@ class UnixSocketInputStream extends InputStream { public int read(byte[] bytesEntry, int off, int len) throws IOException { try { if (off > 0) { - int bytes = 0; - int remainingLength = len; - int size; byte[] data = new byte[(len < 10240) ? len : 10240]; - do { - size = recv(fd, data, (remainingLength < 10240) ? remainingLength : 10240, 0); - if (size > 0) { - System.arraycopy(data, 0, bytesEntry, off, size); - bytes += size; - off += size; - remainingLength -= size; - } - } while ((remainingLength > 0) && (size > 0)); - return bytes; + int size = recv(fd, data, (len < 10240) ? len : 10240, 0); + if (size > 0) { + System.arraycopy(data, 0, bytesEntry, off, size); + } + return size; } else { return recv(fd, bytesEntry, len, 0); } From f648421b89b3520de5ca3f3c429a03edb891e5bd Mon Sep 17 00:00:00 2001 From: Alexander Koshevoy Date: Mon, 2 Nov 2020 21:26:11 +0300 Subject: [PATCH 2/6] Fix potential stuck at UnixDomainSocket.read() (HttpClient transport) (#1475) Prevent unnecessary recurring calls of `read()` on UNIX socket, which may result in blocking read and cause hanging of "docker-java-stream" thread. --- .../httpclient5/UnixDomainSocket.java | 26 +++++++------------ 1 file changed, 9 insertions(+), 17 deletions(-) diff --git a/docker-java-transport-httpclient5/src/main/java/com/github/dockerjava/httpclient5/UnixDomainSocket.java b/docker-java-transport-httpclient5/src/main/java/com/github/dockerjava/httpclient5/UnixDomainSocket.java index cbbfd16a1..cc3c6a647 100644 --- a/docker-java-transport-httpclient5/src/main/java/com/github/dockerjava/httpclient5/UnixDomainSocket.java +++ b/docker-java-transport-httpclient5/src/main/java/com/github/dockerjava/httpclient5/UnixDomainSocket.java @@ -231,24 +231,16 @@ class UnixSocketInputStream extends InputStream { public int read(byte[] bytesEntry, int off, int len) throws IOException { try { if (off > 0) { - int bytes = 0; - int remainingLength = len; - int size; byte[] data = new byte[(len < 10240) ? len : 10240]; - do { - if (!isConnected()) { - return -1; - } - size = UnixDomainSocket.read(fd, data, (remainingLength < 10240) ? remainingLength : 10240); - if (size <= 0) { - return -1; - } - System.arraycopy(data, 0, bytesEntry, off, size); - bytes += size; - off += size; - remainingLength -= size; - } while ((remainingLength > 0) && (size > 0)); - return bytes; + if (!isConnected()) { + return -1; + } + int size = UnixDomainSocket.read(fd, data, (len < 10240) ? len : 10240); + if (size <= 0) { + return -1; + } + System.arraycopy(data, 0, bytesEntry, off, size); + return size; } else { if (!isConnected()) { return -1; From f0e0436e48b470da42436836b52fd968b2aac1f8 Mon Sep 17 00:00:00 2001 From: Alexander Koshevoy Date: Thu, 12 Nov 2020 12:28:45 +0300 Subject: [PATCH 3/6] Use data's length value instead of calculating length once again --- .../com/github/dockerjava/httpclient5/UnixDomainSocket.java | 2 +- .../java/com/github/dockerjava/okhttp/UnixDomainSocket.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docker-java-transport-httpclient5/src/main/java/com/github/dockerjava/httpclient5/UnixDomainSocket.java b/docker-java-transport-httpclient5/src/main/java/com/github/dockerjava/httpclient5/UnixDomainSocket.java index cc3c6a647..9913a1665 100644 --- a/docker-java-transport-httpclient5/src/main/java/com/github/dockerjava/httpclient5/UnixDomainSocket.java +++ b/docker-java-transport-httpclient5/src/main/java/com/github/dockerjava/httpclient5/UnixDomainSocket.java @@ -235,7 +235,7 @@ public int read(byte[] bytesEntry, int off, int len) throws IOException { if (!isConnected()) { return -1; } - int size = UnixDomainSocket.read(fd, data, (len < 10240) ? len : 10240); + int size = UnixDomainSocket.read(fd, data, data.length); if (size <= 0) { return -1; } diff --git a/docker-java-transport-okhttp/src/main/java/com/github/dockerjava/okhttp/UnixDomainSocket.java b/docker-java-transport-okhttp/src/main/java/com/github/dockerjava/okhttp/UnixDomainSocket.java index 04cfe6063..26a23e6fb 100644 --- a/docker-java-transport-okhttp/src/main/java/com/github/dockerjava/okhttp/UnixDomainSocket.java +++ b/docker-java-transport-okhttp/src/main/java/com/github/dockerjava/okhttp/UnixDomainSocket.java @@ -233,7 +233,7 @@ public int read(byte[] bytesEntry, int off, int len) throws IOException { try { if (off > 0) { byte[] data = new byte[(len < 10240) ? len : 10240]; - int size = recv(fd, data, (len < 10240) ? len : 10240, 0); + int size = recv(fd, data, data.length, 0); if (size > 0) { System.arraycopy(data, 0, bytesEntry, off, size); } From 8dceafa068fb7de6ff7785b89cb253d6efa1fe72 Mon Sep 17 00:00:00 2001 From: Alexander Koshevoy Date: Thu, 12 Nov 2020 12:58:39 +0300 Subject: [PATCH 4/6] Let UnixSocketInputStream.read(..) return -1 when the socket is disconnected or EOF is reached --- .../dockerjava/okhttp/UnixDomainSocket.java | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/docker-java-transport-okhttp/src/main/java/com/github/dockerjava/okhttp/UnixDomainSocket.java b/docker-java-transport-okhttp/src/main/java/com/github/dockerjava/okhttp/UnixDomainSocket.java index 26a23e6fb..0ced8a7ed 100644 --- a/docker-java-transport-okhttp/src/main/java/com/github/dockerjava/okhttp/UnixDomainSocket.java +++ b/docker-java-transport-okhttp/src/main/java/com/github/dockerjava/okhttp/UnixDomainSocket.java @@ -230,16 +230,24 @@ class UnixSocketInputStream extends InputStream { @Override public int read(byte[] bytesEntry, int off, int len) throws IOException { + if (!isConnected()) { + return -1; + } try { if (off > 0) { byte[] data = new byte[(len < 10240) ? len : 10240]; int size = recv(fd, data, data.length, 0); - if (size > 0) { - System.arraycopy(data, 0, bytesEntry, off, size); + if (size <= 0) { + return -1; } + System.arraycopy(data, 0, bytesEntry, off, size); return size; } else { - return recv(fd, bytesEntry, len, 0); + int size = recv(fd, bytesEntry, len, 0); + if (size <= 0) { + return -1; + } + return size; } } catch (LastErrorException lee) { throw new IOException("native read() failed : " + formatError(lee)); @@ -250,7 +258,7 @@ public int read(byte[] bytesEntry, int off, int len) throws IOException { public int read() throws IOException { byte[] bytes = new byte[1]; int bytesRead = read(bytes); - if (bytesRead == 0) { + if (bytesRead <= 0) { return -1; } return bytes[0] & 0xff; @@ -258,6 +266,9 @@ public int read() throws IOException { @Override public int read(byte[] bytes) throws IOException { + if (!isConnected()) { + return -1; + } return read(bytes, 0, bytes.length); } } From a3766f795596e35c2e56a9c7dafe070996c514d4 Mon Sep 17 00:00:00 2001 From: Alexander Koshevoy Date: Thu, 12 Nov 2020 13:13:46 +0300 Subject: [PATCH 5/6] Move isConnected() check to the beginning of read(..) method --- .../github/dockerjava/httpclient5/UnixDomainSocket.java | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/docker-java-transport-httpclient5/src/main/java/com/github/dockerjava/httpclient5/UnixDomainSocket.java b/docker-java-transport-httpclient5/src/main/java/com/github/dockerjava/httpclient5/UnixDomainSocket.java index 9913a1665..2ff81b7fd 100644 --- a/docker-java-transport-httpclient5/src/main/java/com/github/dockerjava/httpclient5/UnixDomainSocket.java +++ b/docker-java-transport-httpclient5/src/main/java/com/github/dockerjava/httpclient5/UnixDomainSocket.java @@ -229,12 +229,12 @@ class UnixSocketInputStream extends InputStream { @Override public int read(byte[] bytesEntry, int off, int len) throws IOException { + if (!isConnected()) { + return -1; + } try { if (off > 0) { byte[] data = new byte[(len < 10240) ? len : 10240]; - if (!isConnected()) { - return -1; - } int size = UnixDomainSocket.read(fd, data, data.length); if (size <= 0) { return -1; @@ -242,9 +242,6 @@ public int read(byte[] bytesEntry, int off, int len) throws IOException { System.arraycopy(data, 0, bytesEntry, off, size); return size; } else { - if (!isConnected()) { - return -1; - } int size = UnixDomainSocket.read(fd, bytesEntry, len); if (size <= 0) { return -1; From db86eabe7c9032eeacd7211257ee4cbc0e92c5be Mon Sep 17 00:00:00 2001 From: Alexander Koshevoy Date: Thu, 12 Nov 2020 13:21:39 +0300 Subject: [PATCH 6/6] Make UnixSocketInputStream.read() return -1 if EOF has been reached --- .../com/github/dockerjava/httpclient5/UnixDomainSocket.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker-java-transport-httpclient5/src/main/java/com/github/dockerjava/httpclient5/UnixDomainSocket.java b/docker-java-transport-httpclient5/src/main/java/com/github/dockerjava/httpclient5/UnixDomainSocket.java index 2ff81b7fd..5bdbb85f0 100644 --- a/docker-java-transport-httpclient5/src/main/java/com/github/dockerjava/httpclient5/UnixDomainSocket.java +++ b/docker-java-transport-httpclient5/src/main/java/com/github/dockerjava/httpclient5/UnixDomainSocket.java @@ -257,7 +257,7 @@ public int read(byte[] bytesEntry, int off, int len) throws IOException { public int read() throws IOException { byte[] bytes = new byte[1]; int bytesRead = read(bytes); - if (bytesRead == 0) { + if (bytesRead <= 0) { return -1; } return bytes[0] & 0xff;