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

non-blocking SSL write fails if a partial write was issued #56406

Closed
dsiroky mannequin opened this issue May 27, 2011 · 7 comments
Closed

non-blocking SSL write fails if a partial write was issued #56406

dsiroky mannequin opened this issue May 27, 2011 · 7 comments
Labels
3.7 (EOL) end of life extension-modules C modules in the Modules dir OS-windows topic-SSL type-feature A feature request or enhancement

Comments

@dsiroky
Copy link
Mannequin

dsiroky mannequin commented May 27, 2011

BPO 12197
Nosy @pfmoore, @jcea, @pitrou, @giampaolo, @tiran, @tjguk, @zware, @zooba
Files
  • ssl_sock_test_working_but_blocking.py: example to reproduce (with repeated writes, this works well)
  • ssl_sock_test_fix.py: example to reproduce
  • Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.

    Show more details

    GitHub fields:

    assignee = None
    closed_at = <Date 2017-09-07.02:10:35.011>
    created_at = <Date 2011-05-27.18:06:48.753>
    labels = ['extension-modules', 'expert-SSL', 'type-feature', '3.7', 'OS-windows']
    title = 'non-blocking SSL write fails if a partial write was issued'
    updated_at = <Date 2017-09-07.02:10:35.009>
    user = 'https://bugs.python.org/dsiroky'

    bugs.python.org fields:

    activity = <Date 2017-09-07.02:10:35.009>
    actor = 'christian.heimes'
    assignee = 'none'
    closed = True
    closed_date = <Date 2017-09-07.02:10:35.011>
    closer = 'christian.heimes'
    components = ['Extension Modules', 'Windows', 'SSL']
    creation = <Date 2011-05-27.18:06:48.753>
    creator = 'dsiroky'
    dependencies = []
    files = ['22157', '22280']
    hgrepos = []
    issue_num = 12197
    keywords = []
    message_count = 7.0
    messages = ['137092', '137810', '137898', '137916', '137948', '138116', '301561']
    nosy_count = 9.0
    nosy_names = ['paul.moore', 'jcea', 'pitrou', 'giampaolo.rodola', 'christian.heimes', 'tim.golden', 'dsiroky', 'zach.ware', 'steve.dower']
    pr_nums = []
    priority = 'normal'
    resolution = 'out of date'
    stage = 'resolved'
    status = 'closed'
    superseder = None
    type = 'enhancement'
    url = 'https://bugs.python.org/issue12197'
    versions = ['Python 3.6', 'Python 3.7']

    @dsiroky
    Copy link
    Mannequin Author

    dsiroky mannequin commented May 27, 2011

    Trying to send large bulk of data in MS Windows via non-blocking SSLSocket raises an exception but part of the data is delivered.

    E.g.

    ssl_socket.write(b"a" * 200000)

    raises

    ssl.SSLError: [Errno 3] _ssl.c:1126: The operation did not complete (write)

    There is no way to get the sent bytes count which is essential in non-blocking communication.

    ssl_socket.send() returns 0. This should be unified with posix behavior.

    @dsiroky dsiroky mannequin added type-bug An unexpected behavior, bug, or error extension-modules C modules in the Modules dir OS-windows labels May 27, 2011
    @pitrou
    Copy link
    Member

    pitrou commented Jun 7, 2011

    Which version of Python are you testing on? It works fine using 3.2 and 3.3 here, under Windows 7 64-bit.

    Anyway, I would suggest to batch your write in smaller chunks (say, 2048 bytes each). Also, you may try sendall() instead.

    @dsiroky
    Copy link
    Mannequin Author

    dsiroky mannequin commented Jun 8, 2011

    Sorry, I attached wrong example version. It uses repeated sslsock.write() of the same buffer after catching SSL_ERROR_WANT_WRITE. It delivers the full block but this is a blocking operation.

    I'm troubled with non-blocking writes. But as I dig deeper into the problem it looks like an inconsistency in OpenSSL (Linux vs. MSW). In Linux sslsock.write() always (as far as I can tell) sends some or all of the data and returns the amount. Like the plain socket.send(). In Windows it raises an exception if the data is larger then some uncertain size (mostly 16kB).

    I'm working on snakeMQ asynchronous messaging library where the "packeter" layer relies on the sock.send() returning actual amount of sent bytes. This is not working in Windows if the link uses SSL.

    Tested on WinXP, py2.6, py3.2.

    @pitrou
    Copy link
    Member

    pitrou commented Jun 8, 2011

    Sorry, I attached wrong example version. It uses repeated
    sslsock.write() of the same buffer after catching
    SSL_ERROR_WANT_WRITE. It delivers the full block but this is a
    blocking operation.

    In "normal" non-blocking code you would use select() (or an equivalent)
    until the socket is ready for writing, and then send() some chunk of
    data on it. Can't you use that approach?

    @dsiroky
    Copy link
    Mannequin Author

    dsiroky mannequin commented Jun 9, 2011

    I didn't meant blocking as setblocking(True). I use select/poll but I can't use returned value from send() immediately since in Windows there are often needed more send rounds to actually know how much data was sent.

    E.g. in Linux I know it after the first call:

    sslsock.write("abcd") -> returns 2
    poll(sslsock)
    sslsock.write("cd")

    in Windows I must do:

    sslsock.write("abcd") -> raises SSLError
    poll(sslsock)
    sslsock.write("abcd") -> returns 4

    As I wrote it might be inconsistency in OpenSSL and not in Python's wrapper.

    @pitrou
    Copy link
    Member

    pitrou commented Jun 10, 2011

    I don't see any discrepancy here (with Python 3.3). Under both Linux and Windows, the client thread prints:

    ERR [Errno 3] _ssl.c:1126: The operation did not complete (write)
    done

    The only difference is that the server thread receives 128KB under Linux, and 48KB under Windows.

    I think the main variation comes not from OpenSSL, but from the OS's thread scheduling algorithms. If you do a large write, you have to be prepared to get an error, because the buffers may be too small.

    I agree it might seem strange that OpenSSL returns an error rather than the number of sent bytes, and this behaviour could actually be changed at the OpenSSL level (see http://www.openssl.org/docs/ssl/SSL_write.html) by allowing people to use the SSL_MODE_ENABLE_PARTIAL_WRITE option. However, doing so by default could break existing code which assumes that writes either fail or succeed completely.

    bpo-8240 talks about a slightly related request.

    @pitrou pitrou changed the title non-blocking SSL write in Windows sends large data but raises exception non-blocking SSL write fails if a partial write was issued Jun 10, 2011
    @pitrou pitrou added type-feature A feature request or enhancement and removed type-bug An unexpected behavior, bug, or error labels Jun 10, 2011
    @tiran tiran added 3.7 (EOL) end of life topic-SSL labels Sep 8, 2016
    @tiran tiran self-assigned this Sep 15, 2016
    @tiran
    Copy link
    Member

    tiran commented Sep 7, 2017

    I'm closing this issue because it hasn't seen any activity in six years. Please reopen it with more information if your problem still persists.

    @tiran tiran closed this as completed Sep 7, 2017
    @tiran tiran removed their assignment Sep 7, 2017
    @ezio-melotti ezio-melotti transferred this issue from another repository Apr 10, 2022
    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
    Labels
    3.7 (EOL) end of life extension-modules C modules in the Modules dir OS-windows topic-SSL type-feature A feature request or enhancement
    Projects
    None yet
    Development

    No branches or pull requests

    2 participants