NovaBryan/EVE_Dump
Log | Files | 📦 下载最新源码 (.zip) | Refs | README

servers.py (6889B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\carbon\common\lib\cherrypy\process\servers.py
      2 import sys
      3 import time
      4 
      5 class ServerAdapter(object):
      6 
      7     def __init__(self, bus, httpserver = None, bind_addr = None):
      8         self.bus = bus
      9         self.httpserver = httpserver
     10         self.bind_addr = bind_addr
     11         self.interrupt = None
     12         self.running = False
     13 
     14     def subscribe(self):
     15         self.bus.subscribe('start', self.start)
     16         self.bus.subscribe('stop', self.stop)
     17 
     18     def unsubscribe(self):
     19         self.bus.unsubscribe('start', self.start)
     20         self.bus.unsubscribe('stop', self.stop)
     21 
     22     def start(self):
     23         if self.bind_addr is None:
     24             on_what = 'unknown interface (dynamic?)'
     25         elif isinstance(self.bind_addr, tuple):
     26             host, port = self.bind_addr
     27             on_what = '%s:%s' % (host, port)
     28         else:
     29             on_what = 'socket file: %s' % self.bind_addr
     30         if self.running:
     31             self.bus.log('Already serving on %s' % on_what)
     32             return
     33         self.interrupt = None
     34         if not self.httpserver:
     35             raise ValueError('No HTTP server has been created.')
     36         if isinstance(self.bind_addr, tuple):
     37             wait_for_free_port(*self.bind_addr)
     38         import threading
     39         t = threading.Thread(target=self._start_http_thread)
     40         t.setName('HTTPServer ' + t.getName())
     41         t.start()
     42         self.wait()
     43         self.running = True
     44         self.bus.log('Serving on %s' % on_what)
     45 
     46     start.priority = 75
     47 
     48     def _start_http_thread(self):
     49         try:
     50             self.httpserver.start()
     51         except KeyboardInterrupt:
     52             self.bus.log('<Ctrl-C> hit: shutting down HTTP server')
     53             self.interrupt = sys.exc_info()[1]
     54             self.bus.exit()
     55         except SystemExit:
     56             self.bus.log('SystemExit raised: shutting down HTTP server')
     57             self.interrupt = sys.exc_info()[1]
     58             self.bus.exit()
     59             raise
     60         except:
     61             self.interrupt = sys.exc_info()[1]
     62             self.bus.log('Error in HTTP server: shutting down', traceback=True, level=40)
     63             self.bus.exit()
     64             raise
     65 
     66     def wait(self):
     67         while not getattr(self.httpserver, 'ready', False):
     68             if self.interrupt:
     69                 raise self.interrupt
     70             time.sleep(0.1)
     71 
     72         if isinstance(self.bind_addr, tuple):
     73             host, port = self.bind_addr
     74             wait_for_occupied_port(host, port)
     75 
     76     def stop(self):
     77         if self.running:
     78             self.httpserver.stop()
     79             if isinstance(self.bind_addr, tuple):
     80                 wait_for_free_port(*self.bind_addr)
     81             self.running = False
     82             self.bus.log('HTTP Server %s shut down' % self.httpserver)
     83         else:
     84             self.bus.log('HTTP Server %s already shut down' % self.httpserver)
     85 
     86     stop.priority = 25
     87 
     88     def restart(self):
     89         self.stop()
     90         self.start()
     91 
     92 
     93 class FlupCGIServer(object):
     94 
     95     def __init__(self, *args, **kwargs):
     96         self.args = args
     97         self.kwargs = kwargs
     98         self.ready = False
     99 
    100     def start(self):
    101         from flup.server.cgi import WSGIServer
    102         self.cgiserver = WSGIServer(*self.args, **self.kwargs)
    103         self.ready = True
    104         self.cgiserver.run()
    105 
    106     def stop(self):
    107         self.ready = False
    108 
    109 
    110 class FlupFCGIServer(object):
    111 
    112     def __init__(self, *args, **kwargs):
    113         if kwargs.get('bindAddress', None) is None:
    114             import socket
    115             if not hasattr(socket, 'fromfd'):
    116                 raise ValueError('Dynamic FCGI server not available on this platform. You must use a static or external one by providing a legal bindAddress.')
    117         self.args = args
    118         self.kwargs = kwargs
    119         self.ready = False
    120 
    121     def start(self):
    122         from flup.server.fcgi import WSGIServer
    123         self.fcgiserver = WSGIServer(*self.args, **self.kwargs)
    124         self.fcgiserver._installSignalHandlers = lambda : None
    125         self.fcgiserver._oldSIGs = []
    126         self.ready = True
    127         self.fcgiserver.run()
    128 
    129     def stop(self):
    130         self.fcgiserver._keepGoing = False
    131         self.fcgiserver._threadPool.maxSpare = self.fcgiserver._threadPool._idleCount
    132         self.ready = False
    133 
    134 
    135 class FlupSCGIServer(object):
    136 
    137     def __init__(self, *args, **kwargs):
    138         self.args = args
    139         self.kwargs = kwargs
    140         self.ready = False
    141 
    142     def start(self):
    143         from flup.server.scgi import WSGIServer
    144         self.scgiserver = WSGIServer(*self.args, **self.kwargs)
    145         self.scgiserver._installSignalHandlers = lambda : None
    146         self.scgiserver._oldSIGs = []
    147         self.ready = True
    148         self.scgiserver.run()
    149 
    150     def stop(self):
    151         self.ready = False
    152         self.scgiserver._keepGoing = False
    153         self.scgiserver._threadPool.maxSpare = 0
    154 
    155 
    156 def client_host(server_host):
    157     if server_host == '0.0.0.0':
    158         return '127.0.0.1'
    159     if server_host in ('::', '::0', '::0.0.0.0'):
    160         return '::1'
    161     return server_host
    162 
    163 
    164 def check_port(host, port, timeout = 1.0):
    165     if not host:
    166         raise ValueError("Host values of '' or None are not allowed.")
    167     host = client_host(host)
    168     port = int(port)
    169     import socket
    170     try:
    171         info = socket.getaddrinfo(host, port, socket.AF_UNSPEC, socket.SOCK_STREAM)
    172     except socket.gaierror:
    173         if ':' in host:
    174             info = [(socket.AF_INET6,
    175               socket.SOCK_STREAM,
    176               0,
    177               '',
    178               (host,
    179                port,
    180                0,
    181                0))]
    182         else:
    183             info = [(socket.AF_INET,
    184               socket.SOCK_STREAM,
    185               0,
    186               '',
    187               (host, port))]
    188 
    189     for res in info:
    190         af, socktype, proto, canonname, sa = res
    191         s = None
    192         try:
    193             s = socket.socket(af, socktype, proto)
    194             s.settimeout(timeout)
    195             s.connect((host, port))
    196             s.close()
    197             raise IOError('Port %s is in use on %s; perhaps the previous httpserver did not shut down properly.' % (repr(port), repr(host)))
    198         except socket.error:
    199             if s:
    200                 s.close()
    201 
    202 
    203 def wait_for_free_port(host, port):
    204     if not host:
    205         raise ValueError("Host values of '' or None are not allowed.")
    206     for trial in range(50):
    207         try:
    208             check_port(host, port, timeout=0.1)
    209         except IOError:
    210             time.sleep(0.1)
    211         else:
    212             return
    213 
    214     raise IOError('Port %r not free on %r' % (port, host))
    215 
    216 
    217 def wait_for_occupied_port(host, port):
    218     if not host:
    219         raise ValueError("Host values of '' or None are not allowed.")
    220     for trial in range(50):
    221         try:
    222             check_port(host, port)
    223         except IOError:
    224             return
    225 
    226         time.sleep(0.1)
    227 
    228     raise IOError('Port %r not bound on %r' % (port, host))