<s> from eventlet import patcher <EOL> import functools <EOL> import socket <EOL> from nova import exception <EOL> from nova . i18n import _ <EOL> from hyperv . nova import constants <EOL> threading = patcher . original ( '<STR_LIT>' ) <EOL> def handle_socket_errors ( func ) : <EOL> @ functools . wraps ( func ) <EOL> def wrapper ( self , * args , ** kwargs ) : <EOL> try : <EOL> return func ( self , * args , ** kwargs ) <EOL> except socket . error : <EOL> self . _client_connected . clear ( ) <EOL> return wrapper <EOL> class SerialProxy ( threading . Thread ) : <EOL> def __init__ ( self , instance_name , addr , port , input_queue , <EOL> output_queue , client_connected ) : <EOL> super ( SerialProxy , self ) . __init__ ( ) <EOL> self . setDaemon ( True ) <EOL> self . _instance_name = instance_name <EOL> self . _addr = addr <EOL> self . _port = port <EOL> self . _conn = None <EOL> self . _input_queue = input_queue <EOL> self . _output_queue = output_queue <EOL> self . _client_connected = client_connected <EOL> self . _stopped = threading . Event ( ) <EOL> def _setup_socket ( self ) : <EOL> try : <EOL> self . _sock = socket . socket ( socket . AF_INET , <EOL> socket . SOCK_STREAM ) <EOL> self . _sock . setsockopt ( socket . SOL_SOCKET , <EOL> socket . SO_REUSEADDR , <EOL> <NUM_LIT:1> ) <EOL> self . _sock . bind ( ( self . _addr , self . _port ) ) <EOL> self . _sock . listen ( <NUM_LIT:1> ) <EOL> except socket . error as err : <EOL> self . _sock . close ( ) <EOL> msg = ( _ ( '<STR_LIT>' <EOL> '<STR_LIT>' <EOL> '<STR_LIT>' ) % <EOL> { '<STR_LIT>' : self . _addr , '<STR_LIT:port>' : self . _port , <EOL> '<STR_LIT>' : self . _instance_name , <EOL> '<STR_LIT:error>' : err } ) <EOL> raise exception . NovaException ( msg ) <EOL> def stop ( self ) : <EOL> self . _stopped . set ( ) <EOL> self . _client_connected . clear ( ) <EOL> if self . _conn : <EOL> self . _conn . shutdown ( socket . SHUT_RDWR ) <EOL> self . _conn . close ( ) <EOL> self . _sock . close ( ) <EOL> def run ( self ) : <EOL> self . _setup_socket ( ) <EOL> while not self . _stopped . isSet ( ) : <EOL> self . _accept_conn ( ) <EOL> @ handle_socket_errors <EOL> def _accept_conn ( self ) : <EOL> self . _conn , client_addr = self . _sock . accept ( ) <EOL> self . _client_connected . set ( ) <EOL> workers = [ ] <EOL> for job in [ self . _get_data , self . _send_data ] : <EOL> worker = threading . Thread ( target = job ) <EOL> worker . setDaemon ( True ) <EOL> worker . start ( ) <EOL> workers . append ( worker ) <EOL> for worker in workers : <EOL> worker_running = ( worker . is_alive ( ) and <EOL> worker is not threading . current_thread ( ) ) <EOL> if worker_running : <EOL> worker . join ( ) <EOL> self . _conn . close ( ) <EOL> self . _conn = None <EOL> @ handle_socket_errors <EOL> def _get_data ( self ) : <EOL> while self . _client_connected . isSet ( ) : <EOL> data = self . _conn . recv ( constants . SERIAL_CONSOLE_BUFFER_SIZE ) <EOL> if not data : <EOL> self . _client_connected . clear ( ) <EOL> return <EOL> self . _input_queue . put ( data ) <EOL> @ handle_socket_errors <EOL> def _send_data ( self ) : <EOL> while self . _client_connected . isSet ( ) : <EOL> data = self . _output_queue . get_burst ( ) <EOL> if data : <EOL> self . _conn . sendall ( data ) </s>
