| 53 | | def start(initOnly=False, serverClass=_missing): |
|---|
| 54 | | """Main function. MUST be called from the main thread. |
|---|
| 55 | | |
|---|
| 56 | | Set initOnly to True to keep this function from blocking. |
|---|
| 57 | | Set serverClass to None to skip starting any HTTP server. |
|---|
| 58 | | """ |
|---|
| 59 | | # This duplicates the line in start_app_server on purpose. |
|---|
| 60 | | cherrypy._appserver_state = None |
|---|
| 61 | | cherrypy._interrupt = None |
|---|
| 62 | | |
|---|
| 63 | | conf = cherrypy.config.get |
|---|
| 64 | | |
|---|
| 65 | | if serverClass is _missing: |
|---|
| 66 | | serverClass = conf("server.class", _missing) |
|---|
| 67 | | if serverClass is _missing: |
|---|
| 68 | | import _cpwsgi |
|---|
| 69 | | serverClass = _cpwsgi.WSGIServer |
|---|
| 70 | | elif serverClass and isinstance(serverClass, basestring): |
|---|
| 71 | | # Dynamically load the class from the given string |
|---|
| 72 | | serverClass = cherrypy._cputil.attributes(serverClass) |
|---|
| 73 | | |
|---|
| 74 | | # Autoreload, but check serverClass. If None, we're not starting |
|---|
| 75 | | # our own webserver, and therefore could do Very Bad Things when |
|---|
| 76 | | # autoreload calls sys.exit. |
|---|
| 77 | | if serverClass is not None: |
|---|
| 78 | | defaultOn = (conf("server.environment") == "development") |
|---|
| 79 | | if conf('autoreload.on', defaultOn): |
|---|
| 80 | | try: |
|---|
| 81 | | autoreload.main(_start, (initOnly, serverClass)) |
|---|
| 82 | | except KeyboardInterrupt: |
|---|
| 83 | | cherrypy.log("<Ctrl-C> hit: shutting down autoreloader", "HTTP") |
|---|
| | 52 | |
|---|
| | 53 | class Server(object): |
|---|
| | 54 | |
|---|
| | 55 | def __init__(self): |
|---|
| | 56 | self.state = STOPPED |
|---|
| | 57 | |
|---|
| | 58 | self.httpserver = None |
|---|
| | 59 | self.httpserverclass = None |
|---|
| | 60 | self.interrupt = None |
|---|
| | 61 | |
|---|
| | 62 | # Set some special attributes for adding hooks |
|---|
| | 63 | self.onStartServerList = [] |
|---|
| | 64 | self.onStartThreadList = [] |
|---|
| | 65 | self.onStopServerList = [] |
|---|
| | 66 | self.onStopThreadList = [] |
|---|
| | 67 | |
|---|
| | 68 | def start(self, initOnly=False, serverClass=_missing): |
|---|
| | 69 | """Main function. MUST be called from the main thread. |
|---|
| | 70 | |
|---|
| | 71 | Set initOnly to True to keep this function from blocking. |
|---|
| | 72 | Set serverClass to None to skip starting any HTTP server. |
|---|
| | 73 | """ |
|---|
| | 74 | self.state = STARTING |
|---|
| | 75 | self.interrupt = None |
|---|
| | 76 | |
|---|
| | 77 | conf = cherrypy.config.get |
|---|
| | 78 | |
|---|
| | 79 | if serverClass is _missing: |
|---|
| | 80 | serverClass = conf("server.class", _missing) |
|---|
| | 81 | if serverClass is _missing: |
|---|
| | 82 | import _cpwsgi |
|---|
| | 83 | serverClass = _cpwsgi.WSGIServer |
|---|
| | 84 | elif serverClass and isinstance(serverClass, basestring): |
|---|
| | 85 | # Dynamically load the class from the given string |
|---|
| | 86 | serverClass = cherrypy._cputil.attributes(serverClass) |
|---|
| | 87 | |
|---|
| | 88 | self.blocking = not initOnly |
|---|
| | 89 | self.httpserverclass = serverClass |
|---|
| | 90 | |
|---|
| | 91 | # Autoreload, but check serverClass. If None, we're not starting |
|---|
| | 92 | # our own webserver, and therefore could do Very Bad Things when |
|---|
| | 93 | # autoreload calls sys.exit. |
|---|
| | 94 | if serverClass is not None: |
|---|
| | 95 | defaultOn = (conf("server.environment") == "development") |
|---|
| | 96 | if conf('autoreload.on', defaultOn): |
|---|
| | 97 | try: |
|---|
| | 98 | autoreload.main(self._start) |
|---|
| | 99 | except KeyboardInterrupt: |
|---|
| | 100 | cherrypy.log("<Ctrl-C> hit: shutting down autoreloader", "HTTP") |
|---|
| | 101 | return |
|---|
| | 102 | |
|---|
| | 103 | self._start() |
|---|
| | 104 | |
|---|
| | 105 | def _start(self): |
|---|
| | 106 | # Output config options to log |
|---|
| | 107 | if cherrypy.config.get("server.logConfigOptions", True): |
|---|
| | 108 | cherrypy.config.outputConfigMap() |
|---|
| | 109 | |
|---|
| | 110 | try: |
|---|
| | 111 | configure() |
|---|
| | 112 | |
|---|
| | 113 | for func in cherrypy.server.onStartServerList: |
|---|
| | 114 | func() |
|---|
| | 115 | self.start_http_server() |
|---|
| | 116 | self.state = STARTED |
|---|
| | 117 | |
|---|
| | 118 | if self.blocking: |
|---|
| | 119 | # Block forever (wait for KeyboardInterrupt or SystemExit). |
|---|
| | 120 | while True: |
|---|
| | 121 | time.sleep(.1) |
|---|
| | 122 | if self.interrupt: |
|---|
| | 123 | raise self.interrupt |
|---|
| | 124 | except KeyboardInterrupt: |
|---|
| | 125 | cherrypy.log("<Ctrl-C> hit: shutting down server", "HTTP") |
|---|
| | 126 | self.stop() |
|---|
| | 127 | except SystemExit: |
|---|
| | 128 | cherrypy.log("SystemExit raised: shutting down server", "HTTP") |
|---|
| | 129 | self.stop() |
|---|
| | 130 | |
|---|
| | 131 | def start_http_server(self, blocking=True): |
|---|
| | 132 | """Start the requested HTTP server.""" |
|---|
| | 133 | if self.httpserver is not None: |
|---|
| | 134 | msg = ("You seem to have an HTTP server still running." |
|---|
| | 135 | "Please call server.stop_http_server() " |
|---|
| | 136 | "before continuing.") |
|---|
| | 137 | warnings.warn(msg) |
|---|
| | 138 | |
|---|
| | 139 | if self.httpserverclass is None: |
|---|
| 85 | | |
|---|
| 86 | | _start(initOnly, serverClass) |
|---|
| 87 | | |
|---|
| 88 | | def _start(initOnly, serverClass): |
|---|
| 89 | | # This duplicates the line in start_app_server on purpose. |
|---|
| 90 | | cherrypy._appserver_state = None |
|---|
| 91 | | |
|---|
| 92 | | cherrypy._httpserverclass = serverClass |
|---|
| 93 | | conf = cherrypy.config.get |
|---|
| 94 | | |
|---|
| 95 | | try: |
|---|
| 96 | | if cherrypy.codecoverage: |
|---|
| 97 | | from cherrypy.lib import covercp |
|---|
| 98 | | covercp.start() |
|---|
| 99 | | |
|---|
| 100 | | # Output config options to log |
|---|
| 101 | | if conf("server.logConfigOptions", True): |
|---|
| 102 | | cherrypy.config.outputConfigMap() |
|---|
| 103 | | # TODO: config.checkConfigOptions() |
|---|
| 104 | | |
|---|
| 105 | | # If sessions are stored in files and we |
|---|
| 106 | | # use threading, we need a lock on the file |
|---|
| 107 | | if (conf('server.threadPool') > 1 |
|---|
| 108 | | and conf('session.storageType') == 'file'): |
|---|
| 109 | | cherrypy._sessionFileLock = threading.RLock() |
|---|
| 110 | | |
|---|
| 111 | | # set cgi.maxlen which will limit the size of POST request bodies |
|---|
| 112 | | cgi.maxlen = conf('server.maxRequestSize') |
|---|
| 113 | | |
|---|
| 114 | | # Set up the profiler if requested. |
|---|
| 115 | | if conf("profiling.on", False): |
|---|
| 116 | | ppath = conf("profiling.path", "") |
|---|
| 117 | | cherrypy.profiler = profiler.Profiler(ppath) |
|---|
| 118 | | else: |
|---|
| 119 | | cherrypy.profiler = None |
|---|
| 120 | | |
|---|
| 121 | | # Initialize the built in filters |
|---|
| 122 | | cherrypy._cputil._cpInitDefaultFilters() |
|---|
| 123 | | cherrypy._cputil._cpInitUserDefinedFilters() |
|---|
| 124 | | |
|---|
| 125 | | start_app_server() |
|---|
| 126 | | start_http_server() |
|---|
| 127 | | wait_until_ready() |
|---|
| 128 | | |
|---|
| 129 | | if not initOnly: |
|---|
| 130 | | # Block forever (wait for KeyboardInterrupt or SystemExit). |
|---|
| 131 | | while True: |
|---|
| 132 | | time.sleep(.1) |
|---|
| 133 | | if cherrypy._interrupt: |
|---|
| 134 | | raise cherrypy._interrupt |
|---|
| 135 | | except KeyboardInterrupt: |
|---|
| 136 | | cherrypy.log("<Ctrl-C> hit: shutting down server", "HTTP") |
|---|
| 137 | | stop() |
|---|
| 138 | | except SystemExit: |
|---|
| 139 | | cherrypy.log("SystemExit raised: shutting down server", "HTTP") |
|---|
| 140 | | stop() |
|---|
| 141 | | |
|---|
| 142 | | def start_app_server(): |
|---|
| 143 | | """Start the CherryPy core.""" |
|---|
| 144 | | # Use a flag to indicate the state of the cherrypy application server. |
|---|
| 145 | | # 0 = Not started |
|---|
| 146 | | # None = In process of starting |
|---|
| 147 | | # 1 = Started, ready to receive requests |
|---|
| 148 | | cherrypy._appserver_state = None |
|---|
| 149 | | |
|---|
| 150 | | # Call the functions from cherrypy.server.onStartServerList |
|---|
| 151 | | for func in cherrypy.server.onStartServerList: |
|---|
| 152 | | func() |
|---|
| 153 | | |
|---|
| 154 | | cherrypy._appserver_state = 1 |
|---|
| 155 | | |
|---|
| 156 | | def start_http_server(serverClass=None): |
|---|
| 157 | | """Start the requested HTTP server.""" |
|---|
| 158 | | if serverClass is None: |
|---|
| 159 | | serverClass = cherrypy._httpserverclass |
|---|
| 160 | | if serverClass is None: |
|---|
| 161 | | return |
|---|
| 162 | | |
|---|
| 163 | | if cherrypy._httpserver is not None: |
|---|
| 164 | | msg = ("You seem to have an HTTP server still running." |
|---|
| 165 | | "Please call cherrypy.server.stop_http_server() " |
|---|
| 166 | | "before continuing.") |
|---|
| 167 | | warnings.warn(msg) |
|---|
| 168 | | |
|---|
| 169 | | if cherrypy.config.get('server.socketPort'): |
|---|
| 170 | | host = cherrypy.config.get('server.socketHost') |
|---|
| 171 | | port = cherrypy.config.get('server.socketPort') |
|---|
| 172 | | |
|---|
| 173 | | wait_for_free_port(host, port) |
|---|
| 174 | | |
|---|
| 175 | | if not host: |
|---|
| 176 | | host = 'localhost' |
|---|
| 177 | | onWhat = "http://%s:%s/" % (host, port) |
|---|
| 178 | | else: |
|---|
| 179 | | onWhat = "socket file: %s" % cherrypy.config.get('server.socketFile') |
|---|
| 180 | | cherrypy.log("Serving HTTP on %s" % onWhat, 'HTTP') |
|---|
| 181 | | |
|---|
| 182 | | # Instantiate the server. |
|---|
| 183 | | cherrypy._httpserver = serverClass() |
|---|
| 184 | | |
|---|
| 185 | | # HTTP servers MUST be started in a new thread, so that the |
|---|
| 186 | | # main thread persists to receive KeyboardInterrupt's. This |
|---|
| 187 | | # wrapper traps an interrupt in the http server's main thread |
|---|
| 188 | | # and shutdowns CherryPy. |
|---|
| 189 | | def _start_http(): |
|---|
| 190 | | try: |
|---|
| 191 | | cherrypy._httpserver.start() |
|---|
| 192 | | except (KeyboardInterrupt, SystemExit), exc: |
|---|
| 193 | | cherrypy._interrupt = exc |
|---|
| 194 | | threading.Thread(target=_start_http).start() |
|---|
| 195 | | |
|---|
| 196 | | |
|---|
| 197 | | seen_threads = {} |
|---|
| 198 | | |
|---|
| 199 | | def request(clientAddress, remoteHost, requestLine, headers, rfile, scheme="http"): |
|---|
| 200 | | """request(clientAddress, remoteHost, requestLine, headers, rfile, scheme="http") |
|---|
| 201 | | |
|---|
| 202 | | clientAddress: the (IP address, port) of the client |
|---|
| 203 | | remoteHost: the IP address of the client |
|---|
| 204 | | requestLine: "<HTTP method> <url?qs> HTTP/<version>", |
|---|
| 205 | | e.g. "GET /main?abc=123 HTTP/1.1" |
|---|
| 206 | | headers: a list of (key, value) tuples |
|---|
| 207 | | rfile: a file-like object from which to read the HTTP request body |
|---|
| 208 | | scheme: either "http" or "https"; defaults to "http" |
|---|
| 209 | | """ |
|---|
| 210 | | if cherrypy._appserver_state == 0: |
|---|
| 211 | | raise cherrypy.NotReady("No thread has called cherrypy.server.start().") |
|---|
| 212 | | elif cherrypy._appserver_state == None: |
|---|
| 213 | | raise cherrypy.NotReady("cherrypy.server.start() encountered errors.") |
|---|
| 214 | | |
|---|
| 215 | | threadID = threading._get_ident() |
|---|
| 216 | | if threadID not in seen_threads: |
|---|
| 217 | | |
|---|
| 218 | | if cherrypy.codecoverage: |
|---|
| 219 | | from cherrypy.lib import covercp |
|---|
| 220 | | covercp.start() |
|---|
| 221 | | |
|---|
| 222 | | i = len(seen_threads) + 1 |
|---|
| 223 | | seen_threads[threadID] = i |
|---|
| 224 | | # Call the functions from cherrypy.server.onStartThreadList |
|---|
| 225 | | for func in cherrypy.server.onStartThreadList: |
|---|
| 226 | | func(i) |
|---|
| 227 | | |
|---|
| 228 | | if cherrypy.profiler: |
|---|
| 229 | | cherrypy.profiler.run(_cphttptools.Request, clientAddress, remoteHost, |
|---|
| 230 | | requestLine, headers, rfile, scheme) |
|---|
| 231 | | else: |
|---|
| 232 | | _cphttptools.Request(clientAddress, remoteHost, |
|---|
| 233 | | requestLine, headers, rfile, scheme) |
|---|
| 234 | | |
|---|
| 235 | | def stop(): |
|---|
| 236 | | """Stop CherryPy and any HTTP servers it started.""" |
|---|
| 237 | | stop_http_server() |
|---|
| 238 | | stop_app_server() |
|---|
| 239 | | |
|---|
| 240 | | def stop_app_server(): |
|---|
| 241 | | """Stop CherryPy.""" |
|---|
| 242 | | cherrypy._appserver_state = 0 |
|---|
| 243 | | cherrypy.log("CherryPy shut down", "HTTP") |
|---|
| 244 | | |
|---|
| 245 | | def stop_http_server(): |
|---|
| 246 | | """Stop the HTTP server.""" |
|---|
| 247 | | try: |
|---|
| 248 | | httpstop = cherrypy._httpserver.stop |
|---|
| 249 | | except AttributeError: |
|---|
| 250 | | pass |
|---|
| 251 | | else: |
|---|
| 252 | | # httpstop() MUST block until the server is *truly* stopped. |
|---|
| 253 | | httpstop() |
|---|
| 254 | | cherrypy.log("HTTP Server shut down", "HTTP") |
|---|
| 255 | | |
|---|
| 256 | | # Call the functions from cherrypy.server.onStopThreadList |
|---|
| 257 | | for thread_ident, i in seen_threads.iteritems(): |
|---|
| 258 | | for func in cherrypy.server.onStopThreadList: |
|---|
| 259 | | func(i) |
|---|
| 260 | | seen_threads.clear() |
|---|
| 261 | | |
|---|
| 262 | | # Call the functions from cherrypy.server.onStopServerList |
|---|
| 263 | | for func in cherrypy.server.onStopServerList: |
|---|
| 264 | | func() |
|---|
| 265 | | |
|---|
| 266 | | cherrypy._httpserver = None |
|---|
| 267 | | |
|---|
| 268 | | def restart(): |
|---|
| 269 | | """Restart CherryPy (and any HTTP servers it started).""" |
|---|
| 270 | | stop() |
|---|
| 271 | | start_app_server() |
|---|
| 272 | | start_http_server() |
|---|
| 273 | | wait_until_ready() |
|---|
| 274 | | |
|---|
| 275 | | def wait_until_ready(): |
|---|
| 276 | | """Block the caller until CherryPy is ready to receive requests.""" |
|---|
| 277 | | |
|---|
| 278 | | # Wait for app to start up |
|---|
| 279 | | while cherrypy._appserver_state != 1: |
|---|
| 280 | | time.sleep(.1) |
|---|
| 281 | | |
|---|
| 282 | | # Wait for HTTP server to start up |
|---|
| 283 | | if cherrypy._httpserverclass is not None: |
|---|
| 284 | | while not getattr(cherrypy._httpserver, "ready", None): |
|---|
| 285 | | time.sleep(.1) |
|---|
| 286 | | |
|---|
| 287 | | # Wait for port to be occupied |
|---|
| | 141 | |
|---|
| 291 | | wait_for_occupied_port(host, port) |
|---|
| | 145 | |
|---|
| | 146 | wait_for_free_port(host, port) |
|---|
| | 147 | |
|---|
| | 148 | if not host: |
|---|
| | 149 | host = 'localhost' |
|---|
| | 150 | onWhat = "http://%s:%s/" % (host, port) |
|---|
| | 151 | else: |
|---|
| | 152 | onWhat = "socket file: %s" % cherrypy.config.get('server.socketFile') |
|---|
| | 153 | |
|---|
| | 154 | # Instantiate the server. |
|---|
| | 155 | self.httpserver = self.httpserverclass() |
|---|
| | 156 | |
|---|
| | 157 | # HTTP servers MUST be started in a new thread, so that the |
|---|
| | 158 | # main thread persists to receive KeyboardInterrupt's. This |
|---|
| | 159 | # wrapper traps an interrupt in the http server's main thread |
|---|
| | 160 | # and shutdowns CherryPy. |
|---|
| | 161 | def _start_http(): |
|---|
| | 162 | try: |
|---|
| | 163 | self.httpserver.start() |
|---|
| | 164 | except (KeyboardInterrupt, SystemExit), exc: |
|---|
| | 165 | self.interrupt = exc |
|---|
| | 166 | threading.Thread(target=_start_http).start() |
|---|
| | 167 | |
|---|
| | 168 | if blocking: |
|---|
| | 169 | self.wait_for_http_ready() |
|---|
| | 170 | |
|---|
| | 171 | cherrypy.log("Serving HTTP on %s" % onWhat, 'HTTP') |
|---|
| | 172 | |
|---|
| | 173 | def wait_for_http_ready(self): |
|---|
| | 174 | if self.httpserverclass is not None: |
|---|
| | 175 | while not getattr(self.httpserver, "ready", True): |
|---|
| | 176 | time.sleep(.1) |
|---|
| | 177 | |
|---|
| | 178 | # Wait for port to be occupied |
|---|
| | 179 | if cherrypy.config.get('server.socketPort'): |
|---|
| | 180 | host = cherrypy.config.get('server.socketHost') |
|---|
| | 181 | port = cherrypy.config.get('server.socketPort') |
|---|
| | 182 | wait_for_occupied_port(host, port) |
|---|
| | 183 | |
|---|
| | 184 | def request(self, clientAddress, remoteHost, requestLine, |
|---|
| | 185 | headers, rfile, scheme="http"): |
|---|
| | 186 | """request(clientAddress, remoteHost, requestLine, headers, rfile, scheme="http") |
|---|
| | 187 | |
|---|
| | 188 | clientAddress: the (IP address, port) of the client |
|---|
| | 189 | remoteHost: the IP address of the client |
|---|
| | 190 | requestLine: "<HTTP method> <url?qs> HTTP/<version>", |
|---|
| | 191 | e.g. "GET /main?abc=123 HTTP/1.1" |
|---|
| | 192 | headers: a list of (key, value) tuples |
|---|
| | 193 | rfile: a file-like object from which to read the HTTP request body |
|---|
| | 194 | scheme: either "http" or "https"; defaults to "http" |
|---|
| | 195 | """ |
|---|
| | 196 | if self.state == STOPPED: |
|---|
| | 197 | raise cherrypy.NotReady("The CherryPy server has stopped.") |
|---|
| | 198 | elif self.state == STARTING: |
|---|
| | 199 | raise cherrypy.NotReady("The CherryPy server could not start.") |
|---|
| | 200 | |
|---|
| | 201 | threadID = threading._get_ident() |
|---|
| | 202 | if threadID not in seen_threads: |
|---|
| | 203 | |
|---|
| | 204 | if cherrypy.codecoverage: |
|---|
| | 205 | from cherrypy.lib import covercp |
|---|
| | 206 | covercp.start() |
|---|
| | 207 | |
|---|
| | 208 | i = len(seen_threads) + 1 |
|---|
| | 209 | seen_threads[threadID] = i |
|---|
| | 210 | |
|---|
| | 211 | for func in self.onStartThreadList: |
|---|
| | 212 | func(i) |
|---|
| | 213 | |
|---|
| | 214 | if cherrypy.profiler: |
|---|
| | 215 | cherrypy.profiler.run(_cphttptools.Request, clientAddress, remoteHost, |
|---|
| | 216 | requestLine, headers, rfile, scheme) |
|---|
| | 217 | else: |
|---|
| | 218 | _cphttptools.Request(clientAddress, remoteHost, |
|---|
| | 219 | requestLine, headers, rfile, scheme) |
|---|
| | 220 | |
|---|
| | 221 | def stop(self): |
|---|
| | 222 | """Stop, including any HTTP servers.""" |
|---|
| | 223 | self.stop_http_server() |
|---|
| | 224 | self.state = STOPPED |
|---|
| | 225 | cherrypy.log("CherryPy shut down", "HTTP") |
|---|
| | 226 | |
|---|
| | 227 | def stop_http_server(self): |
|---|
| | 228 | """Stop the HTTP server.""" |
|---|
| | 229 | try: |
|---|
| | 230 | httpstop = self.httpserver.stop |
|---|
| | 231 | except AttributeError: |
|---|
| | 232 | pass |
|---|
| | 233 | else: |
|---|
| | 234 | # httpstop() MUST block until the server is *truly* stopped. |
|---|
| | 235 | httpstop() |
|---|
| | 236 | cherrypy.log("HTTP Server shut down", "HTTP") |
|---|
| | 237 | |
|---|
| | 238 | for thread_ident, i in seen_threads.iteritems(): |
|---|
| | 239 | for func in self.onStopThreadList: |
|---|
| | 240 | func(i) |
|---|
| | 241 | seen_threads.clear() |
|---|
| | 242 | |
|---|
| | 243 | for func in self.onStopServerList: |
|---|
| | 244 | func() |
|---|
| | 245 | |
|---|
| | 246 | self.httpserver = None |
|---|
| | 247 | |
|---|
| | 248 | def restart(self): |
|---|
| | 249 | """Restart, including any HTTP servers.""" |
|---|
| | 250 | self.stop() |
|---|
| | 251 | for func in self.onStartServerList: |
|---|
| | 252 | func() |
|---|
| | 253 | self.state = STARTED |
|---|
| | 254 | self.start_http_server() |
|---|
| | 255 | |
|---|
| | 256 | def wait(self): |
|---|
| | 257 | """Block the caller until ready to receive requests.""" |
|---|
| | 258 | while not self.ready: |
|---|
| | 259 | time.sleep(.1) |
|---|
| | 260 | |
|---|
| | 261 | def _is_ready(self): |
|---|
| | 262 | return bool(self.state == STARTED) |
|---|
| | 263 | ready = property(_is_ready, doc="Return True if the server is ready to receive requests, False otherwise.") |
|---|
| | 264 | |
|---|
| | 265 | def start_with_callback(self, func, args=None, kwargs=None, |
|---|
| | 266 | serverClass=_missing): |
|---|
| | 267 | """Start, then callback the given func in a new thread.""" |
|---|
| | 268 | if args is None: |
|---|
| | 269 | args = () |
|---|
| | 270 | if kwargs is None: |
|---|
| | 271 | kwargs = {} |
|---|
| | 272 | args = (func,) + args |
|---|
| | 273 | |
|---|
| | 274 | def _callback(func, *args, **kwargs): |
|---|
| | 275 | self.wait() |
|---|
| | 276 | func(*args, **kwargs) |
|---|
| | 277 | threading.Thread(target=_callback, args=args, kwargs=kwargs).start() |
|---|
| | 278 | |
|---|
| | 279 | self.start(serverClass=serverClass) |
|---|
| | 280 | |
|---|
| | 281 | |
|---|
| | 282 | def configure(): |
|---|
| | 283 | """Perform one-time actions to prepare the CherryPy core.""" |
|---|
| | 284 | if cherrypy.codecoverage: |
|---|
| | 285 | from cherrypy.lib import covercp |
|---|
| | 286 | covercp.start() |
|---|
| | 287 | |
|---|
| | 288 | conf = cherrypy.config.get |
|---|
| | 289 | # TODO: config.checkConfigOptions() |
|---|
| | 290 | |
|---|
| | 291 | # If sessions are stored in files and we |
|---|
| | 292 | # use threading, we need a lock on the file |
|---|
| | 293 | if (conf('server.threadPool') > 1 |
|---|
| | 294 | and conf('session.storageType') == 'file'): |
|---|
| | 295 | cherrypy._sessionFileLock = threading.RLock() |
|---|
| | 296 | |
|---|
| | 297 | # set cgi.maxlen which will limit the size of POST request bodies |
|---|
| | 298 | cgi.maxlen = conf('server.maxRequestSize') |
|---|
| | 299 | |
|---|
| | 300 | # Set up the profiler if requested. |
|---|
| | 301 | if conf("profiling.on", False): |
|---|
| | 302 | ppath = conf("profiling.path", "") |
|---|
| | 303 | cherrypy.profiler = profiler.Profiler(ppath) |
|---|
| | 304 | else: |
|---|
| | 305 | cherrypy.profiler = None |
|---|
| | 306 | |
|---|
| | 307 | # Initialize the built in filters |
|---|
| | 308 | cherrypy._cputil._cpInitDefaultFilters() |
|---|
| | 309 | cherrypy._cputil._cpInitUserDefinedFilters() |
|---|
| | 310 | |
|---|