Skip to content

Conversation

@minrk
Copy link
Member

@minrk minrk commented Aug 21, 2025

when bind was called with a string (i.e. usually), we encode to bytes before constructing the char * to pass to libzmq. For code re-use purposes, this was consolidated in an inline function. But the problem with creating the bytes object with str.encode() in the inline function is that it gets deallocated when the inline function returns. This has been safe because the actual memory doesn't get freed until the true function returns. However, devmode enables PYTHONMALLOC=debug, which explicitly overwrites memory with PYMEM_DEADBYTE at dereference time (i.e. exit of the inline function), leading (rightly!) to EINVAL because the actual addr we are passing is "\xDD\xDD\xDD\xDD", not the user input.

The fix is to return a Python bytes object from the inline function and hold its reference in the same scope as the pointer to its memory.

I'm not 100% sure why there wasn't an error or warning from Cython and/or C for this, but 🤷 .

closes #2093

minrk added 2 commits August 20, 2025 20:14
uncovers some malloc issues
don't return a pointer after casting in an inline function,
return a Python bytes object from the inline function, get pointer in scope where bytes object resides
@minrk minrk merged commit f6e4446 into zeromq:main Aug 21, 2025
22 checks passed
@minrk minrk deleted the devmode-fix branch August 21, 2025 03:53
@minrk minrk mentioned this pull request Aug 21, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

BUG: socket.bind('tcp://127.0.0.1:...') fails with ZMQError: Invalid argument with Python devmode or PYTHONMALLOC=debug

1 participant