Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

disabling wsgi interface fails under python3 #1377

Closed
ghost opened this issue Jul 19, 2015 · 40 comments · Fixed by #1785
Closed

disabling wsgi interface fails under python3 #1377

ghost opened this issue Jul 19, 2015 · 40 comments · Fixed by #1785

Comments

@ghost
Copy link

ghost commented Jul 19, 2015

Originally reported by: Tim Miller (Bitbucket: lashni, GitHub: Unknown)


http://docs.cherrypy.org/en/latest/advanced.html#no-need-for-the-wsgi-interface

Error is encountered when the example code from the link above is run under a python 3.4.3 virtualenv on archlinux, traceback triggers when the server is accessed. Error doesn't occur with python 2.7.10.

Happens with both current head and CherryPy 3.8.0.

[19/Jul/2015:17:41:01] ENGINE Listening for SIGUSR1.
[19/Jul/2015:17:41:01] ENGINE Listening for SIGTERM.
[19/Jul/2015:17:41:01] ENGINE Listening for SIGHUP.
[19/Jul/2015:17:41:01] ENGINE Bus STARTING
CherryPy Checker:
The Application mounted at '' has an empty config.

[19/Jul/2015:17:41:01] ENGINE Started monitor thread '_TimeoutMonitor'.
[19/Jul/2015:17:41:01] ENGINE Started monitor thread 'Autoreloader'.
[19/Jul/2015:17:41:01] ENGINE Serving on http://127.0.0.1:8080
[19/Jul/2015:17:41:01] ENGINE Bus STARTED
[19/Jul/2015:17:41:05] NATIVE_ADAPTER Traceback (most recent call last):
  File "/home/lashni/dev/serve/lib/python3.4/site-packages/cherrypy/_cpnative_server.py", line 27, in respond
    sn = cherrypy.tree.script_name(req.uri or "/")
  File "/home/lashni/dev/serve/lib/python3.4/site-packages/cherrypy/_cptree.py", line 257, in script_name
    path = path[:path.rfind("/")]
TypeError: 'str' does not support the buffer interface

ValueError('invalid literal for int() with base 10: "b\'5"',)
Traceback (most recent call last):
  File "/home/lashni/dev/serve/lib/python3.4/site-packages/cherrypy/_cpnative_server.py", line 27, in respond
    sn = cherrypy.tree.script_name(req.uri or "/")
  File "/home/lashni/dev/serve/lib/python3.4/site-packages/cherrypy/_cptree.py", line 257, in script_name
    path = path[:path.rfind("/")]
TypeError: 'str' does not support the buffer interface

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/lashni/dev/serve/lib/python3.4/site-packages/cherrypy/wsgiserver/wsgiserver3.py", line 1068, in communicate
    req.respond()
  File "/home/lashni/dev/serve/lib/python3.4/site-packages/cherrypy/wsgiserver/wsgiserver3.py", line 856, in respond
    self.server.gateway(self).respond()
  File "/home/lashni/dev/serve/lib/python3.4/site-packages/cherrypy/_cpnative_server.py", line 88, in respond
    self.send_response(s, h, b)
  File "/home/lashni/dev/serve/lib/python3.4/site-packages/cherrypy/_cpnative_server.py", line 101, in send_response
    req.send_headers()
  File "/home/lashni/dev/serve/lib/python3.4/site-packages/cherrypy/wsgiserver/wsgiserver3.py", line 912, in send_headers
    status = int(self.status[:3])
ValueError: invalid literal for int() with base 10: "b'5"

@sevmonster
Copy link

sevmonster commented May 27, 2016

This also occurs for me, not tested under other Python versions.
The fact that this has existed since as early as 3.8.0 up to 5.4.0 surprises me.
OS is Win7, Python 3.5.1, CherryPy 5.4.0, not behind any other proxies or load balancers.

Example server setup, based on my own:

cherrypy.config.update({'global': {
    'server.socket_host':                   '0.0.0.0',
    'server.socket_port':                   8081,

    'server.https.socket_host':             '0.0.0.0',
    'server.https.socket_port':             444,
    'server.https.ssl_module':             'builtin',
    'server.https.ssl_certificate':        'example_cert.pem',
    'server.https.ssl_private_key':        'example_key.pem',
    'server.https.ssl_certificate_chain' : 'example_chain.pem',
}})

from cherrypy._cpnative_server import CPHTTPServer
for s in (cherrypy.server, *cherrypy.servers.values()):
    s.httpserver = CPHTTPServer(s)

Trace:

>python -mexample_http_server
[26/May/2016:18:41:41] ENGINE Bus STARTING
[26/May/2016:18:41:41] ENGINE Started monitor thread 'Autoreloader'.
[26/May/2016:18:41:41] ENGINE Started monitor thread '_TimeoutMonitor'.
[26/May/2016:18:41:42] ENGINE Serving on http://0.0.0.0:8081
[26/May/2016:18:41:42] ENGINE Serving on https://0.0.0.0:444
[26/May/2016:18:41:42] ENGINE Bus STARTED

...making a request to either server...

[26/May/2016:18:41:42] NATIVE_ADAPTER Traceback (most recent call last):
  File "C:\Python35\lib\site-packages\cherrypy\_cpnative_server.py", line 27, in respond
    sn = cherrypy.tree.script_name(req.uri or "/")
  File "C:\Python35\lib\site-packages\cherrypy\_cptree.py", line 257, in script_name
    path = path[:path.rfind("/")]
TypeError: a bytes-like object is required, not 'str'

ValueError('invalid literal for int() with base 10: "b\'5"',)
Traceback (most recent call last):
  File "C:\Python35\lib\site-packages\cherrypy\_cpnative_server.py", line 27, in respond
    sn = cherrypy.tree.script_name(req.uri or "/")
  File "C:\Python35\lib\site-packages\cherrypy\_cptree.py", line 257, in script_name
    path = path[:path.rfind("/")]
TypeError: a bytes-like object is required, not 'str'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "C:\Python35\lib\site-packages\cherrypy\wsgiserver\wsgiserver3.py", line 1091, in communicate
    req.respond()
  File "C:\Python35\lib\site-packages\cherrypy\wsgiserver\wsgiserver3.py", line 879, in respond
    self.server.gateway(self).respond()
  File "C:\Python35\lib\site-packages\cherrypy\_cpnative_server.py", line 88, in respond
    self.send_response(s, h, b)
  File "C:\Python35\lib\site-packages\cherrypy\_cpnative_server.py", line 101, in send_response
    req.send_headers()
  File "C:\Python35\lib\site-packages\cherrypy\wsgiserver\wsgiserver3.py", line 935, in send_headers
    status = int(self.status[:3])
ValueError: invalid literal for int() with base 10: "b'5"

...NATIVE_ADAPTER traceback repeated 5 more times...

I followed the docs to the letter, so I'm not entirely sure what the issue is.
Happens for both server instances, as well as when instantiating and accessing just one.

@jaraco jaraco added critical and removed minor labels May 27, 2016
@jaraco
Copy link
Member

jaraco commented Dec 27, 2016

I can confirm this issue persists even after the wsgiserver refactor:

  File "/Users/jaraco/Dropbox/code/public/cherrypy/cherrypy/_cpnative_server.py", line 27, in respond
    sn = cherrypy.tree.script_name(req.uri or '/')
  File "/Users/jaraco/Dropbox/code/public/cherrypy/cherrypy/_cptree.py", line 259, in script_name
    path = path[:path.rfind('/')]
TypeError: a bytes-like object is required, not 'str'

ValueError('invalid literal for int() with base 10: "b\'5"',)
Traceback (most recent call last):
  File "/Users/jaraco/Dropbox/code/public/cherrypy/cherrypy/_cpnative_server.py", line 27, in respond
    sn = cherrypy.tree.script_name(req.uri or '/')
  File "/Users/jaraco/Dropbox/code/public/cherrypy/cherrypy/_cptree.py", line 259, in script_name
    path = path[:path.rfind('/')]
TypeError: a bytes-like object is required, not 'str'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/Users/jaraco/Dropbox/code/public/cherrypy/cherrypy/wsgiserver/__init__.py", line 1408, in communicate
    req.respond()
  File "/Users/jaraco/Dropbox/code/public/cherrypy/cherrypy/wsgiserver/__init__.py", line 862, in respond
    self.server.gateway(self).respond()
  File "/Users/jaraco/Dropbox/code/public/cherrypy/cherrypy/_cpnative_server.py", line 88, in respond
    self.send_response(s, h, b)
  File "/Users/jaraco/Dropbox/code/public/cherrypy/cherrypy/_cpnative_server.py", line 101, in send_response
    req.send_headers()
  File "/Users/jaraco/Dropbox/code/public/cherrypy/cherrypy/wsgiserver/__init__.py", line 923, in send_headers
    status = int(self.status[:3])
ValueError: invalid literal for int() with base 10: "b'5"

@webknjaz
Copy link
Member

Hmm.. What about now + cheroot?

@Kodiologist
Copy link

Kodiologist commented May 23, 2018

Looks like this bug is still there. I just hit it with Python 3.6.5 and CherryPy 15.0.0. Using the documentation's example:

    import cherrypy

    class Root(object):
        @cherrypy.expose
        def index(self):
            return "Hello World!"

    if __name__ == '__main__':
        from cherrypy._cpnative_server import CPHTTPServer
        cherrypy.server.httpserver = CPHTTPServer(cherrypy.server)

        cherrypy.quickstart(Root(), '/')

the stack trace I get is:

    [23/May/2018:10:21:16] NATIVE_ADAPTER Traceback (most recent call last):
      File "/usr/local/lib/python3.6/dist-packages/cherrypy/_cpnative_server.py", line 30, in respond
        sn = cherrypy.tree.script_name(req.uri or '/')
      File "/usr/local/lib/python3.6/dist-packages/cherrypy/_cptree.py", line 268, in script_name
        path = path[:path.rfind('/')]
    TypeError: a bytes-like object is required, not 'str'

    ValueError('invalid literal for int() with base 10: "b\'5"',)
    Traceback (most recent call last):
      File "/usr/local/lib/python3.6/dist-packages/cherrypy/_cpnative_server.py", line 30, in respond
        sn = cherrypy.tree.script_name(req.uri or '/')
      File "/usr/local/lib/python3.6/dist-packages/cherrypy/_cptree.py", line 268, in script_name
        path = path[:path.rfind('/')]
    TypeError: a bytes-like object is required, not 'str'

    During handling of the above exception, another exception occurred:

    Traceback (most recent call last):
      File "/usr/local/lib/python3.6/dist-packages/cheroot/server.py", line 1193, in communicate
        req.respond()
      File "/usr/local/lib/python3.6/dist-packages/cheroot/server.py", line 997, in respond
        self.server.gateway(self).respond()
      File "/usr/local/lib/python3.6/dist-packages/cherrypy/_cpnative_server.py", line 91, in respond
        self.send_response(s, h, b)
      File "/usr/local/lib/python3.6/dist-packages/cherrypy/_cpnative_server.py", line 105, in send_response
        req.send_headers()
      File "/usr/local/lib/python3.6/dist-packages/cheroot/server.py", line 1061, in send_headers
        status = int(self.status[:3])
    ValueError: invalid literal for int() with base 10: "b'5"

@webknjaz
Copy link
Member

@jaraco turns out, there's incorrect processing of bytes vs str in several places over this module.

ValueError: invalid literal for int() with base 10: "b'5"

It tried to "b'500 Internal Server Error'" get 3 digits from this thing, which looks like a repr.

TypeError: a bytes-like object is required, not 'str'

This originates in this line:

sn = cherrypy.tree.script_name(req.uri or '/')


req.uri is of type bytes as well as req.status, but something went wrong while passing those things back and forth.

@webknjaz
Copy link
Member

I've started fixing some things, but still need some time/help: #1712

/cc: @jaraco

@jaraco
Copy link
Member

jaraco commented May 28, 2018

As I'm trying to replicate the issue with that patch above, I'm running into another error (#1697):

cherrypy bugfix/1377-add-test $ tox -- test-1377.py -s
python develop-inst-nodeps: /Users/jaraco/Dropbox/code/public/cherrypy
python installed: atomicwrites==1.1.5,attrs==18.1.0,backports.functools-lru-cache==1.5,backports.unittest-mock==1.3,certifi==2018.4.16,chardet==3.0.4,cheroot==6.3.1,-e git+gh://cherrypy/cherrypy@348799ff7b23f4fcb6f165a8b4c774d81a6ca712#egg=CherryPy,codecov==2.0.15,coverage==4.5.1,graphviz==0.8.3,idna==2.6,more-itertools==4.2.0,objgraph==3.4.0,path.py==11.0.1,pluggy==0.6.0,portend==2.2,py==1.5.3,pytest==3.6.0,pytest-cov==2.5.1,pytest-sugar==0.9.1,pytz==2018.4,repoze.lru==0.7,requests==2.18.4,requests-toolbelt==0.8.0,Routes==2.4.1,six==1.11.0,tempora==1.11,termcolor==1.1.0,urllib3==1.22
python runtests: PYTHONHASHSEED='2081565896'
python runtests: commands[0] | mkdir -p /Users/jaraco/Dropbox/code/public/cherrypy/.test-results/pytest
python runtests: commands[1] | pytest test-1377.py -s
Test session starts (platform: darwin, Python 3.7.0, pytest 3.6.0, pytest-sugar 0.9.1)
cachedir: .pytest_cache
rootdir: /Users/jaraco/Dropbox/code/public/cherrypy, inifile: pytest.ini
plugins: sugar-0.9.1, cov-2.5.1, backports.unittest-mock-1.3
[28/May/2018:14:15:41] ENGINE Bus STARTING
[28/May/2018:14:15:41] ENGINE Started monitor thread 'Autoreloader'.
[28/May/2018:14:15:42] ENGINE Error in background task thread function <bound method Autoreloader.run of <cherrypy.process.plugins.Autoreloaderobject at 0x103e960f0>>.
Traceback (most recent call last):
  File "/Users/jaraco/Dropbox/code/public/cherrypy/cherrypy/process/plugins.py", line 518, in run
    self.function(*self.args, **self.kwargs)
  File "/Users/jaraco/Dropbox/code/public/cherrypy/cherrypy/process/plugins.py", line 667, in run
    for filename in self.sysfiles() | self.files:
  File "/Users/jaraco/Dropbox/code/public/cherrypy/cherrypy/process/plugins.py", line 632, in sysfiles
    return set(filter(None, map(self._file_for_module, mods)))
  File "/Users/jaraco/Dropbox/code/public/cherrypy/cherrypy/process/plugins.py", line 639, in _file_for_module
    or cls._file_for_file_module(module)
  File "/Users/jaraco/Dropbox/code/public/cherrypy/cherrypy/process/plugins.py", line 654, in _file_for_file_module
    return cls._make_absolute(module.__file__)
  File "/Users/jaraco/Dropbox/code/public/cherrypy/cherrypy/process/plugins.py", line 661, in _make_absolute
    return filename if os.path.isabs(filename) else (
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/posixpath.py", line 66, in isabs
    s = os.fspath(s)
TypeError: expected str, bytes or os.PathLike object, not NoneType

Exception in thread Autoreloader:
Traceback (most recent call last):
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/threading.py", line 917, in _bootstrap_inner
    self.run()
  File "/Users/jaraco/Dropbox/code/public/cherrypy/cherrypy/process/plugins.py", line 518, in run
    self.function(*self.args, **self.kwargs)
  File "/Users/jaraco/Dropbox/code/public/cherrypy/cherrypy/process/plugins.py", line 667, in run
    for filename in self.sysfiles() | self.files:
  File "/Users/jaraco/Dropbox/code/public/cherrypy/cherrypy/process/plugins.py", line 632, in sysfiles
    return set(filter(None, map(self._file_for_module, mods)))
  File "/Users/jaraco/Dropbox/code/public/cherrypy/cherrypy/process/plugins.py", line 639, in _file_for_module
    or cls._file_for_file_module(module)
  File "/Users/jaraco/Dropbox/code/public/cherrypy/cherrypy/process/plugins.py", line 654, in _file_for_file_module
    return cls._make_absolute(module.__file__)
  File "/Users/jaraco/Dropbox/code/public/cherrypy/cherrypy/process/plugins.py", line 661, in _make_absolute
    return filename if os.path.isabs(filename) else (
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/posixpath.py", line 66, in isabs
    s = os.fspath(s)
TypeError: expected str, bytes or os.PathLike object, not NoneType

[28/May/2018:14:15:46] ENGINE Error in 'start' listener <bound method Server.start of <cherrypy._cpserver.Server object at 0x103ead278>>
Traceback (most recent call last):
  File "/Users/jaraco/Dropbox/code/public/cherrypy/cherrypy/process/wspbus.py", line 230, in publish
    output.append(listener(*args, **kwargs))
  File "/Users/jaraco/Dropbox/code/public/cherrypy/cherrypy/_cpserver.py", line 191, in start
    super(Server, self).start()
  File "/Users/jaraco/Dropbox/code/public/cherrypy/cherrypy/process/servers.py", line 184, in start
    self.wait()
  File "/Users/jaraco/Dropbox/code/public/cherrypy/cherrypy/process/servers.py", line 260, in wait
    portend.occupied(*self.bound_addr, timeout=Timeouts.occupied)
  File "/Users/jaraco/Dropbox/code/public/cherrypy/.tox/python/lib/python3.7/site-packages/portend.py", line 151, in occupied
    raise Timeout("Port {port} not bound on {host}.".format(**locals()))
portend.Timeout: Port 59434 not bound on 127.0.0.1.

[28/May/2018:14:15:46] ENGINE Shutting down due to error in start listener:
Traceback (most recent call last):
  File "/Users/jaraco/Dropbox/code/public/cherrypy/cherrypy/process/wspbus.py", line 268, in start
    self.publish('start')
  File "/Users/jaraco/Dropbox/code/public/cherrypy/cherrypy/process/wspbus.py", line 248, in publish
    raise exc
cherrypy.process.wspbus.ChannelFailures: Timeout('Port 59434 not bound on 127.0.0.1.')

[28/May/2018:14:15:46] ENGINE Bus STOPPING
[28/May/2018:14:15:46] ENGINE HTTP Server cherrypy._cpnative_server.CPHTTPServer(('127.0.0.1', 8080)) already shut down
[28/May/2018:14:15:46] ENGINE Stopped thread 'Autoreloader'.
[28/May/2018:14:15:46] ENGINE Bus STOPPED
[28/May/2018:14:15:46] ENGINE Bus EXITING
[28/May/2018:14:15:46] ENGINE Bus EXITED
ERROR: InvocationError for command '/Users/jaraco/Dropbox/code/public/cherrypy/.tox/python/bin/pytest test-1377.py -s' (exited with code 70)
___________________________________________________________________ summary ____________________________________________________________________
ERROR:   python: commands failed

@webknjaz
Copy link
Member

@jaraco yes, exactly. that's why it's WIP

@webknjaz
Copy link
Member

You could try Python 3.6 for now

@jaraco
Copy link
Member

jaraco commented May 28, 2018

I've fixed #1697 and now I'm getting the same result on my test branch on Python 3.7 and 3.6:

cherrypy bugfix/1377-add-test $ tox -e py36 -- test-1377.py -s
py36 create: /Users/jaraco/Dropbox/code/public/cherrypy/.tox/py36
py36 develop-inst: /Users/jaraco/Dropbox/code/public/cherrypy
py36 installed: You are using pip version 9.0.1, however version 10.0.1 is available.,You should consider upgrading via the 'pip install --upgrade pip' command.,atomicwrites==1.1.5,attrs==18.1.0,backports.functools-lru-cache==1.5,backports.unittest-mock==1.3,certifi==2018.4.16,chardet==3.0.4,cheroot==6.3.1,-e git+gh://cherrypy/cherrypy@86ce228bdb55b4d74b55e70154d4816cdc355a53#egg=CherryPy,codecov==2.0.15,coverage==4.5.1,graphviz==0.8.3,idna==2.6,more-itertools==4.2.0,objgraph==3.4.0,path.py==11.0.1,pluggy==0.6.0,portend==2.2,py==1.5.3,pytest==3.6.0,pytest-cov==2.5.1,pytest-sugar==0.9.1,pytz==2018.4,repoze.lru==0.7,requests==2.18.4,requests-toolbelt==0.8.0,Routes==2.4.1,six==1.11.0,tempora==1.11,termcolor==1.1.0,urllib3==1.22
py36 runtests: PYTHONHASHSEED='3159197583'
py36 runtests: commands[0] | mkdir -p /Users/jaraco/Dropbox/code/public/cherrypy/.test-results/pytest
py36 runtests: commands[1] | pytest test-1377.py -s
Test session starts (platform: darwin, Python 3.6.4, pytest 3.6.0, pytest-sugar 0.9.1)
cachedir: .pytest_cache
rootdir: /Users/jaraco/Dropbox/code/public/cherrypy, inifile: pytest.ini
plugins: sugar-0.9.1, cov-2.5.1, backports.unittest-mock-1.3
[28/May/2018:14:35:57] ENGINE Bus STARTING
[28/May/2018:14:35:57] ENGINE Started monitor thread 'Autoreloader'.
[28/May/2018:14:36:03] ENGINE Error in 'start' listener <bound method Server.start of <cherrypy._cpserver.Server object at 0x10d821630>>
Traceback (most recent call last):
  File "/Users/jaraco/Dropbox/code/public/cherrypy/cherrypy/process/wspbus.py", line 230, in publish
    output.append(listener(*args, **kwargs))
  File "/Users/jaraco/Dropbox/code/public/cherrypy/cherrypy/_cpserver.py", line 191, in start
    super(Server, self).start()
  File "/Users/jaraco/Dropbox/code/public/cherrypy/cherrypy/process/servers.py", line 184, in start
    self.wait()
  File "/Users/jaraco/Dropbox/code/public/cherrypy/cherrypy/process/servers.py", line 260, in wait
    portend.occupied(*self.bound_addr, timeout=Timeouts.occupied)
  File "/Users/jaraco/Dropbox/code/public/cherrypy/.tox/py36/lib/python3.6/site-packages/portend.py", line 151, in occupied
    raise Timeout("Port {port} not bound on {host}.".format(**locals()))
portend.Timeout: Port 59851 not bound on 127.0.0.1.

[28/May/2018:14:36:03] ENGINE Shutting down due to error in start listener:
Traceback (most recent call last):
  File "/Users/jaraco/Dropbox/code/public/cherrypy/cherrypy/process/wspbus.py", line 268, in start
    self.publish('start')
  File "/Users/jaraco/Dropbox/code/public/cherrypy/cherrypy/process/wspbus.py", line 248, in publish
    raise exc
cherrypy.process.wspbus.ChannelFailures: Timeout('Port 59851 not bound on 127.0.0.1.',)

[28/May/2018:14:36:03] ENGINE Bus STOPPING
[28/May/2018:14:36:03] ENGINE HTTP Server cherrypy._cpnative_server.CPHTTPServer(('127.0.0.1', 8080)) already shut down
[28/May/2018:14:36:03] ENGINE Stopped thread 'Autoreloader'.
[28/May/2018:14:36:03] ENGINE Bus STOPPED
[28/May/2018:14:36:03] ENGINE Bus EXITING
[28/May/2018:14:36:03] ENGINE Bus EXITED
ERROR: InvocationError for command '/Users/jaraco/Dropbox/code/public/cherrypy/.tox/py36/bin/pytest test-1377.py -s' (exited with code 70)
___________________________________________________________________ summary ____________________________________________________________________
ERROR:   py36: commands failed

I'm still unsuccessful in setting up a native HTTP server. Any idea what I'm doing wrong in attempting to replicate the reported issue?

@webknjaz
Copy link
Member

@jaraco try not changing port and sticking to default. I experienced some issues (I didn't find out why) when trying to change port, but it worked (replicated) with default port setting.

jaraco added a commit that referenced this issue May 29, 2018
@jaraco
Copy link
Member

jaraco commented May 29, 2018

Indeed. That seems like another bug (or limitation, maybe). Working with the default port, the test now replicates the reported failure. Thanks for the tip.

@webknjaz
Copy link
Member

@jaraco this is still open, but changelog for v16.0.0 mentions some change related to it. Could you please verify this?

@webknjaz
Copy link
Member

Oh, Cheroot is probably irrelevant..

But some STR would be useful.

@webknjaz
Copy link
Member

@webknjaz
Copy link
Member

6cc67e0

@jaraco do you remember anything wrt this?

@jaraco
Copy link
Member

jaraco commented Sep 25, 2018

If I recall correctly, the tests were using Unix sockets, so the tests couldn’t run on Windows. Still, some things were fixed. Probably better to open a new issue at this point for ongoing issues. Link to this one for reference.

@webknjaz
Copy link
Member

@jaraco, no, those unix socket tests are in cheroot

@jaraco
Copy link
Member

jaraco commented Oct 17, 2018

hmm. Okay. Reviewing that change, it does seem that I disabled the test without a good reason (other than it was failing and I wanted to get the fix out that was passing on Unix). We should revisit and investigate why it's failing on Windows only and get that fixed too.

@Kodiologist
Copy link

I'm seeing what looking like the same old error on Linux. I'm running Ubuntu 19.04, Python 3.7.3, CherryPy 18.1.1, and cheroot 6.5.5. Here's the output from running the example code and trying to visit http://127.0.0.1:8080:

[27/May/2019:10:41:25] ENGINE Listening for SIGTERM.
[27/May/2019:10:41:25] ENGINE Listening for SIGHUP.
[27/May/2019:10:41:25] ENGINE Listening for SIGUSR1.
[27/May/2019:10:41:25] ENGINE Bus STARTING
CherryPy Checker:
The Application mounted at '' has an empty config.

[27/May/2019:10:41:25] ENGINE Started monitor thread 'Autoreloader'.
[27/May/2019:10:41:25] ENGINE Serving on http://127.0.0.1:8080
[27/May/2019:10:41:25] ENGINE Bus STARTED
[27/May/2019:10:41:34] NATIVE_ADAPTER Traceback (most recent call last):
  File "/usr/local/lib/python3.7/dist-packages/cherrypy/_cpnative_server.py", line 30, in respond
    sn = cherrypy.tree.script_name(req.uri or '/')
  File "/usr/local/lib/python3.7/dist-packages/cherrypy/_cptree.py", line 281, in script_name
    path = path[:path.rfind('/')]
TypeError: argument should be integer or bytes-like object, not 'str'

[27/May/2019:10:41:34] NATIVE_ADAPTER Traceback (most recent call last):
  File "/usr/local/lib/python3.7/dist-packages/cherrypy/_cpnative_server.py", line 30, in respond
    sn = cherrypy.tree.script_name(req.uri or '/')
  File "/usr/local/lib/python3.7/dist-packages/cherrypy/_cptree.py", line 281, in script_name
    path = path[:path.rfind('/')]
TypeError: argument should be integer or bytes-like object, not 'str'

@webknjaz
Copy link
Member

@Kodiologist mind submitting a test for this? I think we need to improve bytes/unicode conversion...

@Kodiologist
Copy link

Sure, I'll try it out.

@Kodiologist
Copy link

I wrote this test, but it seems to pass, instead of failing as it ought to.

import cherrypy
from cherrypy.test import helper

class Root(object):
    @cherrypy.expose
    def index(self):
        return 'payload'

class T(helper.CPWebCase):

    @staticmethod
    def setup_server():
        from cherrypy._cpnative_server import CPHTTPServer
        cherrypy.server.httpserver = CPHTTPServer(cherrypy.server)

        cherrypy.tree.mount(root=Root())

    def test_cpnative(self):
        self.getPage('/')
        self.assertStatus('200 OK')
        self.assertBody('payload')

@webknjaz
Copy link
Member

@Kodiologist could you submit that as a PR plz so that we could see whether it'll happen in the CI?

@Kodiologist
Copy link

@webknjaz Done as #1784.

@webknjaz
Copy link
Member

Apparently, a similar test already exists: https://github.com/cherrypy/cherrypy/pull/1712/files#diff-38455dfb545934fdb8aaae27bbfd32adR33. And it doesn't fail for a mysterious reason.

cc @jaraco

@webknjaz
Copy link
Member

I've submitted a fix here: #1785.
It works for me when I use that reproducer. But I want to integrate a proper test before merging.

@webknjaz
Copy link
Member

I've released the fix under v18.1.2 and v17.4.2.
Thanks @Kodiologist for assistance with the reproducer!

@MSayfullin
Copy link

It looks like this fix breaks server in some circumstances, @webknjaz
After upgrading to the latest v18.1.2 our servers stop responding from time to time and we have such exceptions in log:

[08/Jul/2019:17:00:48] ENGINE socket.error 1
Traceback (most recent call last):
  File "/home/pt/.local/lib/python3.5/site-packages/cheroot/server.py", line 1219, in communicate
    req.parse_request()
  File "/home/pt/.local/lib/python3.5/site-packages/cheroot/server.py", line 689, in parse_request
    success = self.read_request_line()
  File "/home/pt/.local/lib/python3.5/site-packages/cheroot/server.py", line 728, in read_request_line
    request_line = self.rfile.readline()
  File "/home/pt/.local/lib/python3.5/site-packages/cheroot/server.py", line 277, in readline
    data = self.rfile.readline(256)
  File "/usr/lib/python3.5/_pyio.py", line 510, in readline
    b = self.read(nreadahead())
  File "/usr/lib/python3.5/_pyio.py", line 494, in nreadahead
    readahead = self.peek(1)
  File "/usr/lib/python3.5/_pyio.py", line 1062, in peek
    return self._peek_unlocked(size)
  File "/usr/lib/python3.5/_pyio.py", line 1069, in _peek_unlocked
    current = self.raw.read(to_read)
  File "/usr/lib/python3.5/socket.py", line 575, in readinto
    return self._sock.recv_into(b)
  File "/usr/lib/python3.5/ssl.py", line 929, in recv_into
    return self.read(nbytes, buffer)
  File "/usr/lib/python3.5/ssl.py", line 791, in read
    return self._sslobj.read(len, buffer)
  File "/usr/lib/python3.5/ssl.py", line 575, in read
    v = self._sslobj.read(len, buffer)
ssl.SSLError: [SSL: DECRYPTION_FAILED_OR_BAD_RECORD_MAC] decryption failed or bad record mac (_ssl.c:1977)

Sometimes there will be several of them, sometimes hundreds but at the end application becomes completely unresponsive. No CPU load, no additional memory consumption, nothing new in logs. All requests are just timing out.
Downgrading back to v18.1.1 resolves this issue.

This was happening sporadically but constantly. Most probably because of some specific combination of request data which, unfortunately, we couldn't recognize.

We use Ubuntu 16.04 LTS.

@webknjaz
Copy link
Member

@MSayfullin looks like that's a Cheroot issue which manifests itself with a combination with a certain version of the OpenSSL. Please create a new issue under Cheroot and fill in all of the required details and include a minimal reproducer if possible.

@MSayfullin
Copy link

@webknjaz thanks for getting back to me.
Unfortunately, we've already rolled back to a previous version of cherrypy and production environment doesn't fail anymore. We cannot reproduce it in a test environment as well because we didn't catch that specific combination of request params.

What concerns me also is that according to a history of releases in GitHub cheroot's latest one is dated by January 14 and cherrypy version which works for us (v18.1.1) is released on March 27th. This makes me believe that both versions v18.1.1 and v18.1.2 use the same cheroot version and only change that could affect our app is PR #1785

@webknjaz
Copy link
Member

This doesn't look related to that PR at all. Are you sure you used the same Cheroot version in both cases? Do you pin your env deps versions?

@MSayfullin
Copy link

We didn't update or downgrade cheroot version and still use 6.2.4. Hope this helps, @webknjaz

@webknjaz
Copy link
Member

Well, then my best guess is that you were updating something related to openssl on the OS level maybe.

@MSayfullin
Copy link

That's the thing, only thing updated was cherrypy :)

@webknjaz
Copy link
Member

Anyway, this needs a real reproducer and a separate issue. The info provided isn't sufficient to conclude any relation to this change.

@jaraco
Copy link
Member

jaraco commented Oct 4, 2019

I don't think we can realistically roll back this change, but do feel free to open a new bug (preferably with a means to reproduce the issue) to track the regression/degradation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Bugs
Backlog
Development

Successfully merging a pull request may close this issue.

6 participants