Fix callback handling and flag initialization - #629
Conversation
|
Thanks for this PR! How can I reproduce the errors? Does this need a certain CFFI version? |
You can reproduce (I'm very sure) by installing Python v3.14.4 w/cffi 2.0.0 and Sounddevice with 0.5.5, then use any application that opens a stream for a long time. As mentioned I applied some fixes to my sd installation and it has not been causing any more issues. |
|
I could not reproduce this on a Windows VM using any host API, so this bug might be more specific to your hardware. I have the feeling your fix just hides an underlying problem, which should be fixed in CFFI or PortAudio (I don't know where the bug actually is). Can you show the output of Can you try it with different host APIs? Can you try it with different sound cards? When the error appears, can you check which exact type the last argument in You could try this by creating a file named import faulthandler
import sounddevice as sd
faulthandler.enable()
_wrap_callback = sd._wrap_callback
def _instrumented_wrap_callback(callback, *args):
status = args[-1]
if type(status) is not int:
print('ERROR: status is a', type(status))
return sd._lib.paAbort
try:
str(sd.CallbackFlags(status))
except BaseException as e:
print('ERROR:', repr(e))
return sd._lib.paAbort
return _wrap_callback(callback, *args)
sd._wrap_callback = _instrumented_wrap_callback... and import it at the very top or your code: import instrumented
... # the rest of your program, as you ran it before |
Problem
On Python 3.14, cffi changed how it passes arguments to native callbacks
and how it validates
__init__return values. This caused two distinct errors:TypeError: __init__() should return None, not 'NoneType'cffi now intercepts and validates the return of
__init__at a lowerlevel, causing it to spuriously reject the standard
Nonereturn.TypeError: unsupported operand type(s) for &: '_CDataBase' and 'int'The
statusargument now arrives as a raw_CDataBaseobject insteadof a plain Python int, breaking bitwise operations in
_hasflag.Both errors surface in
_wrap_callbackand occur unpredictably duringstream callbacks, including during silence and active playback.
Fix
Bypass
CallbackFlags.__init__entirely in_wrap_callbackusing__new__, then set_flagsdirectly viaint()cast. This avoidsthe cffi
__init__interception and the_CDataBasebitwise issuein one shot.
Changes
In
_wrap_callback, replace:With:
Tested on