nicolas-van/pygreen

Ctrl-C Should Quit the server at once.

Closed this issue · 4 comments

Sometimes hitting Ctrl-C does not kill the server, but prints a 'KeyboardInterrupt' Traceback instead and keeps running.

I already had that error too, but I can't reproduce it any more. If it happens to you again, could you copy-paste the whole stack trace here?

Thanks in advance.

Got one:

^CTraceback (most recent call last):
  File "/usr/lib/python2.7/wsgiref/handlers.py", line 85, in run
    self.result = application(self.environ, self.start_response)
  File "/usr/local/bin/bottle.py", line 874, in __call__
    return self.wsgi(environ, start_response)
  File "/usr/local/bin/bottle.py", line 849, in wsgi
    out = self._cast(self._handle(environ))
  File "/usr/local/bin/bottle.py", line 764, in _handle
    return route.call(**args)
  File "/usr/local/bin/bottle.py", line 1575, in wrapper
    rv = callback(*a, **ka)
  File "/usr/local/lib/python2.7/dist-packages/pygreen-1.0.2-py2.7.egg/pygreen.py", line 88, in hello
    t = self.templates.get_template(path)
  File "/usr/local/lib/python2.7/dist-packages/mako/lookup.py", line 245, in get_template
    return self._load(srcfile, uri)
  File "/usr/local/lib/python2.7/dist-packages/mako/lookup.py", line 311, in _load
    **self.template_args)
  File "/usr/local/lib/python2.7/dist-packages/mako/template.py", line 321, in __init__
    module = self._compile_from_file(path, filename)
  File "/usr/local/lib/python2.7/dist-packages/mako/template.py", line 399, in _compile_from_file
    filename)
  File "/usr/local/lib/python2.7/dist-packages/mako/template.py", line 647, in _compile_text
    generate_magic_comment=template.disable_unicode)
  File "/usr/local/lib/python2.7/dist-packages/mako/template.py", line 628, in _compile
    node = lexer.parse()
  File "/usr/local/lib/python2.7/dist-packages/mako/lexer.py", line 244, in parse
    if self.match_text():
  File "/usr/local/lib/python2.7/dist-packages/mako/lexer.py", line 356, in match_text
    )""", re.X | re.S)
  File "/usr/local/lib/python2.7/dist-packages/mako/lexer.py", line 59, in match
    reg = re.compile(regexp, flags)
  File "/usr/lib/python2.7/re.py", line 190, in compile
    return _compile(pattern, flags)
  File "/usr/lib/python2.7/re.py", line 240, in _compile
    p = sre_compile.compile(pattern, flags)
  File "/usr/lib/python2.7/sre_compile.py", line 500, in compile
    p = sre_parse.parse(p, flags)
  File "/usr/lib/python2.7/sre_parse.py", line 673, in parse
    p = _parse_sub(source, pattern, 0)
  File "/usr/lib/python2.7/sre_parse.py", line 308, in _parse_sub
    itemsappend(_parse(source, state))
  File "/usr/lib/python2.7/sre_parse.py", line 633, in _parse
    p = _parse_sub(source, state)
  File "/usr/lib/python2.7/sre_parse.py", line 308, in _parse_sub
    itemsappend(_parse(source, state))
  File "/usr/lib/python2.7/sre_parse.py", line 589, in _parse
    p = _parse_sub(source, state)
  File "/usr/lib/python2.7/sre_parse.py", line 308, in _parse_sub
    itemsappend(_parse(source, state))
  File "/usr/lib/python2.7/sre_parse.py", line 490, in _parse
    if sourcematch(","):
  File "/usr/lib/python2.7/sre_parse.py", line 196, in match
    if char == self.next:
KeyboardInterrupt

Attempt to correct that: by redefining a custom http server:

def run(self, **kwargs):
    """
    Launch a development web server.
    """
    kwargs.setdefault("host", "0.0.0.0")
    class SuperSimpleServer(bottle.ServerAdapter):
        def run(self, handler):
            from wsgiref.simple_server import make_server
            stop = {"val": False}
            def nhandler(env, sr):
                try:
                    return handler(env, sr)
                except KeyboardInterrupt:
                    stop["val"] = True
                    sr(b'200 OK', [])
                    return [b" "]
            srv = make_server(self.host, self.port, nhandler, **self.options)
            while not stop["val"]:
                try:
                    srv.handle_request()
                except KeyboardInterrupt:
                    stop["val"] = True
    bottle.run(self.app, server=SuperSimpleServer, **kwargs)

Still can fail in rare cases:

^C----------------------------------------
Exception happened during processing of request from ('127.0.0.1', 36922)
Traceback (most recent call last):
  File "/usr/lib/python2.7/SocketServer.py", line 284, in _handle_request_noblock
    self.process_request(request, client_address)
  File "/usr/lib/python2.7/SocketServer.py", line 310, in process_request
    self.finish_request(request, client_address)
  File "/usr/lib/python2.7/SocketServer.py", line 323, in finish_request
    self.RequestHandlerClass(request, client_address, self)
  File "/usr/lib/python2.7/SocketServer.py", line 638, in __init__
    self.handle()
  File "/usr/lib/python2.7/wsgiref/simple_server.py", line 117, in handle
    if not self.parse_request(): # An error code has been sent, just exit
  File "/usr/lib/python2.7/BaseHTTPServer.py", line 250, in parse_request
    if len(words) == 3:
KeyboardInterrupt
----------------------------------------

Ok, after some investigation this problem comes from wsgiref, the simple web server used to test bottles applications. I can't really do much thing about that, if it's buggy it's buggy.

Although I considered the possibility to switch to another web server, since bottle easily allow to choose the one you prefer. The last commit now uses waitress, which seems pretty cool. It's a lot faster, stops correctly most of the time and doesn't seem to have any downsides except the fact I have to add a dependency. It still rarely prints some error messages when hitting ctrl+C, but all the web servers I tested had the same problem. So you'll have to live with that.