From 208bcbfebcd5587775beed18f642dd8592cbcba9 Mon Sep 17 00:00:00 2001 From: Imogen <59090860+ImogenBits@users.noreply.github.com> Date: Sun, 23 Apr 2023 22:08:43 +0200 Subject: [PATCH 1/7] Use WaitForSingleObject in recv_into Signed-off-by: Imogen <59090860+ImogenBits@users.noreply.github.com> --- docker/transport/npipesocket.py | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/docker/transport/npipesocket.py b/docker/transport/npipesocket.py index 766372aefd..46e2d7fc75 100644 --- a/docker/transport/npipesocket.py +++ b/docker/transport/npipesocket.py @@ -4,6 +4,8 @@ import win32file import win32pipe +import pywintypes +import win32event cERROR_PIPE_BUSY = 0xe7 cSECURITY_SQOS_PRESENT = 0x100000 @@ -131,13 +133,22 @@ def recv_into(self, buf, nbytes=0): if not isinstance(buf, memoryview): readbuf = memoryview(buf) + event = win32event.CreateEvent(None, True, True, None) + overlapped = pywintypes.OVERLAPPED() + overlapped.hEvent = event err, data = win32file.ReadFile( self._handle, - readbuf[:nbytes] if nbytes else readbuf + readbuf[:nbytes] if nbytes else readbuf, + overlapped ) - return len(data) + wait_result = win32event.WaitForSingleObject(event, self._timeout) + if wait_result == win32event.WAIT_TIMEOUT: + win32file.CancelIo(self._handle) + raise TimeoutError + return win32file.GetOverlappedResult(self._handle, overlapped, 0) def _recv_into_py2(self, buf, nbytes): + raise RuntimeError err, data = win32file.ReadFile(self._handle, nbytes or len(buf)) n = len(data) buf[:n] = data @@ -165,12 +176,9 @@ def setblocking(self, flag): def settimeout(self, value): if value is None: # Blocking mode - self._timeout = win32pipe.NMPWAIT_WAIT_FOREVER + self._timeout = win32event.INFINITE elif not isinstance(value, (float, int)) or value < 0: raise ValueError('Timeout value out of range') - elif value == 0: - # Non-blocking mode - self._timeout = win32pipe.NMPWAIT_NO_WAIT else: # Timeout mode - Value converted to milliseconds self._timeout = value * 1000 From f861f1c65de14d5fea3f211e961dff8587ccef46 Mon Sep 17 00:00:00 2001 From: Imogen <59090860+ImogenBits@users.noreply.github.com> Date: Sun, 23 Apr 2023 22:09:08 +0200 Subject: [PATCH 2/7] create file handle with async mode Signed-off-by: Imogen <59090860+ImogenBits@users.noreply.github.com> --- docker/transport/npipesocket.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/transport/npipesocket.py b/docker/transport/npipesocket.py index 46e2d7fc75..585b6a67e0 100644 --- a/docker/transport/npipesocket.py +++ b/docker/transport/npipesocket.py @@ -56,7 +56,7 @@ def connect(self, address, retry_count=0): 0, None, win32file.OPEN_EXISTING, - cSECURITY_ANONYMOUS | cSECURITY_SQOS_PRESENT, + cSECURITY_ANONYMOUS | cSECURITY_SQOS_PRESENT | win32file.FILE_FLAG_OVERLAPPED, 0 ) except win32pipe.error as e: From 2e08ad0fba68278f7dc578a5678adc60cce0044e Mon Sep 17 00:00:00 2001 From: Imogen <59090860+ImogenBits@users.noreply.github.com> Date: Sun, 23 Apr 2023 22:09:19 +0200 Subject: [PATCH 3/7] use WaitForSingleObject in send Signed-off-by: Imogen <59090860+ImogenBits@users.noreply.github.com> --- docker/transport/npipesocket.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/docker/transport/npipesocket.py b/docker/transport/npipesocket.py index 585b6a67e0..e8f6ba66a4 100644 --- a/docker/transport/npipesocket.py +++ b/docker/transport/npipesocket.py @@ -156,8 +156,15 @@ def _recv_into_py2(self, buf, nbytes): @check_closed def send(self, string, flags=0): - err, nbytes = win32file.WriteFile(self._handle, string) - return nbytes + event = win32event.CreateEvent(None, True, True, None) + overlapped = pywintypes.OVERLAPPED() + overlapped.hEvent = event + win32file.WriteFile(self._handle, string, overlapped) + wait_result = win32event.WaitForSingleObject(event, self._timeout) + if wait_result == win32event.WAIT_TIMEOUT: + win32file.CancelIo(self._handle) + raise TimeoutError + return win32file.GetOverlappedResult(self._handle, overlapped, 0) @check_closed def sendall(self, string, flags=0): From 0a147b7121a607cec3aebdb936addf4d197a08ed Mon Sep 17 00:00:00 2001 From: Imogen <59090860+ImogenBits@users.noreply.github.com> Date: Sun, 23 Apr 2023 22:09:48 +0200 Subject: [PATCH 4/7] round timeout to int Signed-off-by: Imogen <59090860+ImogenBits@users.noreply.github.com> --- docker/transport/npipesocket.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/transport/npipesocket.py b/docker/transport/npipesocket.py index e8f6ba66a4..10622e2b18 100644 --- a/docker/transport/npipesocket.py +++ b/docker/transport/npipesocket.py @@ -188,7 +188,7 @@ def settimeout(self, value): raise ValueError('Timeout value out of range') else: # Timeout mode - Value converted to milliseconds - self._timeout = value * 1000 + self._timeout = int(value * 1000) def gettimeout(self): return self._timeout From 05599cd3589649d50b9a344c913ca85dc7f95d8a Mon Sep 17 00:00:00 2001 From: Imogen <59090860+ImogenBits@users.noreply.github.com> Date: Sat, 6 May 2023 11:12:49 +0200 Subject: [PATCH 5/7] remove python 2 code Signed-off-by: Imogen <59090860+ImogenBits@users.noreply.github.com> --- docker/transport/npipesocket.py | 7 ------- 1 file changed, 7 deletions(-) diff --git a/docker/transport/npipesocket.py b/docker/transport/npipesocket.py index 10622e2b18..18ccf25441 100644 --- a/docker/transport/npipesocket.py +++ b/docker/transport/npipesocket.py @@ -147,13 +147,6 @@ def recv_into(self, buf, nbytes=0): raise TimeoutError return win32file.GetOverlappedResult(self._handle, overlapped, 0) - def _recv_into_py2(self, buf, nbytes): - raise RuntimeError - err, data = win32file.ReadFile(self._handle, nbytes or len(buf)) - n = len(data) - buf[:n] = data - return n - @check_closed def send(self, string, flags=0): event = win32event.CreateEvent(None, True, True, None) From 81601c86f8927b0958865d148eb4024549d975af Mon Sep 17 00:00:00 2001 From: Imogen <59090860+ImogenBits@users.noreply.github.com> Date: Sat, 6 May 2023 12:14:04 +0200 Subject: [PATCH 6/7] Close event handle after reading/writing Signed-off-by: Imogen <59090860+ImogenBits@users.noreply.github.com> --- docker/transport/npipesocket.py | 47 +++++++++++++++++++-------------- 1 file changed, 27 insertions(+), 20 deletions(-) diff --git a/docker/transport/npipesocket.py b/docker/transport/npipesocket.py index 18ccf25441..ce4558601e 100644 --- a/docker/transport/npipesocket.py +++ b/docker/transport/npipesocket.py @@ -6,6 +6,7 @@ import win32pipe import pywintypes import win32event +import win32api cERROR_PIPE_BUSY = 0xe7 cSECURITY_SQOS_PRESENT = 0x100000 @@ -134,30 +135,36 @@ def recv_into(self, buf, nbytes=0): readbuf = memoryview(buf) event = win32event.CreateEvent(None, True, True, None) - overlapped = pywintypes.OVERLAPPED() - overlapped.hEvent = event - err, data = win32file.ReadFile( - self._handle, - readbuf[:nbytes] if nbytes else readbuf, - overlapped - ) - wait_result = win32event.WaitForSingleObject(event, self._timeout) - if wait_result == win32event.WAIT_TIMEOUT: - win32file.CancelIo(self._handle) - raise TimeoutError - return win32file.GetOverlappedResult(self._handle, overlapped, 0) + try: + overlapped = pywintypes.OVERLAPPED() + overlapped.hEvent = event + err, data = win32file.ReadFile( + self._handle, + readbuf[:nbytes] if nbytes else readbuf, + overlapped + ) + wait_result = win32event.WaitForSingleObject(event, self._timeout) + if wait_result == win32event.WAIT_TIMEOUT: + win32file.CancelIo(self._handle) + raise TimeoutError + return win32file.GetOverlappedResult(self._handle, overlapped, 0) + finally: + win32api.CloseHandle(event) @check_closed def send(self, string, flags=0): event = win32event.CreateEvent(None, True, True, None) - overlapped = pywintypes.OVERLAPPED() - overlapped.hEvent = event - win32file.WriteFile(self._handle, string, overlapped) - wait_result = win32event.WaitForSingleObject(event, self._timeout) - if wait_result == win32event.WAIT_TIMEOUT: - win32file.CancelIo(self._handle) - raise TimeoutError - return win32file.GetOverlappedResult(self._handle, overlapped, 0) + try: + overlapped = pywintypes.OVERLAPPED() + overlapped.hEvent = event + win32file.WriteFile(self._handle, string, overlapped) + wait_result = win32event.WaitForSingleObject(event, self._timeout) + if wait_result == win32event.WAIT_TIMEOUT: + win32file.CancelIo(self._handle) + raise TimeoutError + return win32file.GetOverlappedResult(self._handle, overlapped, 0) + finally: + win32api.CloseHandle(event) @check_closed def sendall(self, string, flags=0): From 228cba2ff660b039f9c8495c4381005a8a18b4ee Mon Sep 17 00:00:00 2001 From: Imogen <59090860+ImogenBits@users.noreply.github.com> Date: Mon, 8 May 2023 12:11:50 +0200 Subject: [PATCH 7/7] fix line width Signed-off-by: Imogen <59090860+ImogenBits@users.noreply.github.com> --- docker/transport/npipesocket.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docker/transport/npipesocket.py b/docker/transport/npipesocket.py index ce4558601e..9cbe40cc7f 100644 --- a/docker/transport/npipesocket.py +++ b/docker/transport/npipesocket.py @@ -57,7 +57,9 @@ def connect(self, address, retry_count=0): 0, None, win32file.OPEN_EXISTING, - cSECURITY_ANONYMOUS | cSECURITY_SQOS_PRESENT | win32file.FILE_FLAG_OVERLAPPED, + (cSECURITY_ANONYMOUS + | cSECURITY_SQOS_PRESENT + | win32file.FILE_FLAG_OVERLAPPED), 0 ) except win32pipe.error as e: