-
Notifications
You must be signed in to change notification settings - Fork 11
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Implement the background mode in Windows.
Signed-off-by: Hongli Chen <[email protected]>
- Loading branch information
1 parent
dd77eaa
commit f2a3547
Showing
17 changed files
with
547 additions
and
54 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -23,3 +23,5 @@ __pycache__/ | |
/dist | ||
_version.py | ||
.vscode | ||
.coverage | ||
.idea/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
115 changes: 115 additions & 0 deletions
115
src/openjd/adaptor_runtime/_background/backend_named_pipe_server.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
|
||
from __future__ import annotations | ||
import logging | ||
|
||
import threading | ||
import time | ||
|
||
from queue import Queue | ||
from typing import List | ||
|
||
from .named_pipe_request_handler import WinBackgroundResourceRequestHandler | ||
from .server_config import NAMED_PIPE_BUFFER_SIZE, DEFAULT_NAMED_PIPE_TIMEOUT | ||
from .server_response import AsyncFutureRunner | ||
from .._osname import OSName | ||
|
||
if OSName.is_windows(): | ||
import win32pipe | ||
import win32file | ||
import pywintypes | ||
import winerror | ||
from pywintypes import HANDLE | ||
|
||
from ..adaptors import AdaptorRunner | ||
from .log_buffers import LogBuffer | ||
|
||
|
||
_logger = logging.getLogger(__name__) | ||
|
||
|
||
class WinBackgroundNamedPipeServer: | ||
""" | ||
HTTP server for the background mode of the adaptor runtime communicating via Unix socket. | ||
This UnixStreamServer subclass stores the stateful information of the adaptor backend. | ||
""" | ||
|
||
def __init__( | ||
self, | ||
pipe_name: str, | ||
adaptor_runner: AdaptorRunner, | ||
cancel_queue: Queue, | ||
*, | ||
log_buffer: LogBuffer | None = None, | ||
) -> None: # pragma: no cover | ||
self._adaptor_runner = adaptor_runner | ||
self._cancel_queue = cancel_queue | ||
self._future_runner = AsyncFutureRunner() | ||
self._log_buffer = log_buffer | ||
self._named_pipe_instances: List[HANDLE] = [] | ||
self._pipe_name = pipe_name | ||
self._time_out = DEFAULT_NAMED_PIPE_TIMEOUT | ||
|
||
def _create_pipe(self, pipe_name: str): | ||
# Create the first instance of a specific named pipe | ||
# OR Create a new instance of an existing named pipe. | ||
pipe_handle = win32pipe.CreateNamedPipe( | ||
pipe_name, | ||
# A bi-directional pipe; both server and client processes can read from and write to the pipe. | ||
# win32file.FILE_FLAG_OVERLAPPED is used for async communication. | ||
win32pipe.PIPE_ACCESS_DUPLEX | win32file.FILE_FLAG_OVERLAPPED, | ||
win32pipe.PIPE_TYPE_MESSAGE | win32pipe.PIPE_READMODE_MESSAGE | win32pipe.PIPE_WAIT, | ||
win32pipe.PIPE_UNLIMITED_INSTANCES, | ||
NAMED_PIPE_BUFFER_SIZE, # nOutBufferSize | ||
NAMED_PIPE_BUFFER_SIZE, # nInBufferSize | ||
self._time_out, | ||
None, # TODO: Add lpSecurityAttributes here to limit the access | ||
) | ||
if pipe_handle == win32file.INVALID_HANDLE_VALUE: | ||
_logger.error("Failed to create named pipe instance.") | ||
return None | ||
return pipe_handle | ||
|
||
def serve_forever(self): | ||
# During shutdown, a `True` will be pushed to the `_cancel_queue` for ending this loop | ||
_logger.info(f"Creating Named Pipe with name: {self._pipe_name}") | ||
|
||
while self._cancel_queue.qsize() == 0: | ||
pipe_handle = self._create_pipe(self._pipe_name) | ||
self._named_pipe_instances.append(pipe_handle) | ||
_logger.debug("Waiting for connection from the client...") | ||
|
||
try: | ||
win32pipe.ConnectNamedPipe(pipe_handle, None) | ||
except pywintypes.error as e: | ||
if e.winerror == winerror.ERROR_PIPE_NOT_CONNECTED: | ||
_logger.info( | ||
"NamedPipe Server is shutdown. Exit the main thread in the backend server." | ||
) | ||
break | ||
request_handler = WinBackgroundResourceRequestHandler(self, pipe_handle) | ||
threading.Thread(target=request_handler.instance_thread).start() | ||
|
||
def shutdown(self): | ||
self._cancel_queue.put(True) | ||
# TODO: Need to find out a better way to wait for the communication finish | ||
# After sending the shutdown command, we need to wait for the response | ||
# from it before shutting down server or the client won't get the response. | ||
time.sleep(1) | ||
for pipe_handle in self._named_pipe_instances: | ||
try: | ||
win32pipe.DisconnectNamedPipe(pipe_handle) | ||
win32file.CloseHandle(pipe_handle) | ||
except pywintypes.error as e: | ||
# If the communication is finished then handler may be closed | ||
if e.args[0] == winerror.ERROR_INVALID_HANDLE: | ||
pass | ||
except Exception as e: | ||
import traceback | ||
|
||
_logger.error( | ||
"Meeting an error during shutdown the NamedPipe Server:", | ||
str(traceback.format_exc()), | ||
) | ||
raise e |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.