New issue 2578: Behavioral discrepancy between CPython and PyPy ssl modules https://bitbucket.org/pypy/pypy/issues/2578/behavioral-discrepancy-between-cpython-and
Nathaniel Smith: Here's a weird edge case where the CPython and PyPy ssl modules behave differently. I'm not entirely sure whether it's a bug or not, and it's easy enough for me to work around, but I found the PyPy behavior surprising and who knows it might point to some deeper issue, so I wanted to make a formal note. Scenario: * Client and server negotiate a TLS connection * Client sends `close_notify` then immediately closes socket * Server receives `close_notify` then attempts to send `close_notify` back In this scenario, on CPython the server gets a `BrokenPipeError`, which makes sense – this is the usual error for trying to send data on a socket that the other side already closed. On PyPy, the server gets a `SSLEOFError: EOF occurred in violation of protocol`. This is (a) different, and (b) the text is not true, the EOF was totally legal. (Quoth RFC 5246: "Unless some other fatal alert has been transmitted, each party is required to send a close_notify alert before closing the write side of the connection. The other party MUST respond with a close_notify alert of its own and close down the connection immediately, discarding any pending writes. It is not required for the initiator of the close to wait for the responding close_notify alert before closing the read side of the connection.") Weirdly, running under strace I can see PyPy getting `EPIPE` before raising `SSLEOFError`, and then the next syscall it makes is to start looking up python files so it can print the traceback: ``` [pid 17390] write(4, "\25\3\3\0\32\211\327\250b\301+o\373$\363\32\t\r\231\261\256\322\f\230\362\205vr\224VD", 31) = -1 EPIPE (Broken pipe) [pid 17390] --- SIGPIPE {si_signo=SIGPIPE, si_code=SI_USER, si_pid=17387, si_uid=1000} --- [pid 17390] stat("/home/njs/pypy/pypy3.5-5.8-beta-linux_x86_64-portable/lib-python/3/threading.py", {st_mode=S_IFREG|0644, st_size=48919, ...}) = 0 ``` And looking at the definition of `pyssl_error` in lib_pypy/_cffi_ssl/_stdssl/error.py, it looks like the difference between raising `SSLEOFError` and an `OSError` like `BrokenPipeError` is the setting of a "did the BIO indicate an error" flag. If that flag is broken in general then that's definitely worrisome. Sample code here: https://gist.github.com/njsmith/7cf06383adca0392c862cfa22cb70804 CC: @alex_gaynor _______________________________________________ pypy-issue mailing list pypy-issue@python.org https://mail.python.org/mailman/listinfo/pypy-issue