python-sounddevice
python-sounddevice copied to clipboard
python -m sounddevice crashes the python.exe process
There is no exception our backtrace in the output, just the standard window dialog pop-up "python.exe has stopped working".
I've narrowed it down to sounddevice.py:2731 stdio = _ffi.dlopen(None)
I tried this both with python 2.7 as well as 3.7 (both 64-bit).
Running on Windows 10 64-bit.
Thanks for the report!
Can you please run the following code and tell me what happens?
from cffi import FFI
ffi = FFI()
lib = ffi.dlopen(None)
print(lib)
<cffi.api.FFILibrary object at 0x000000000453A3C8>
No crash during this test. However, I've noticed that _sounddevice.py
imports FFI via the binary file _cffi_backend.pyd
rather than from the cffi
as in your example.
Thanks for the test!
Since that didn't expose the error, we'll have to dig deeper.
Can you please run the following code (which now uses _cffi_backend
)?
import _cffi_backend
ffi = _cffi_backend.FFI('_dummy',
_version = 0x2601,
_types = b'\x00\x00\x05\x0D\x00\x00\x08\x03\x00\x00\x01\x11\x00\x00\x00\x0F\x00\x00\x09\x0D\x00\x00\x07\x03\x00\x00\x00\x0F\x00\x00\x00\x09\x00\x00\x02\x01\x00\x00\x07\x01',
_globals = (b'\x00\x00\x05\x21__stderrp',0,b'\x00\x00\x04\x23fclose',0,b'\x00\x00\x00\x23fopen',0,b'\x00\x00\x05\x21stderr',0),
_struct_unions = ((b'\x00\x00\x00\x07\x00\x00\x00\x10_IO_FILE',),),
_typenames = (b'\x00\x00\x00\x07FILE',),
)
stdio = ffi.dlopen(None)
print(stdio)
Crashes in the exact same way.
Great, now we have a much smaller test case!
Maybe we can reduce it even more:
import _cffi_backend
ffi = _cffi_backend.FFI()
stdio = ffi.dlopen(None)
print(stdio)
What does this do?
What if you replace None
with some string, like e.g. ffi.dlopen('nonsense')
?
What if you replace it by the empty string?
What version of CFFI are you using?
Can you upgrade CFFI (latest release is 1.14.0)?
Example above using None still crashes. Nonsensical inputs return "OSError: cannot load library" as expected. Seems to be the problem with loading the C standard library or maybe any actual library that is found (at least judging from looking at the cffi/api.py which i assume this is a binary precompiled version of - haven't looked into how this works yet).
I'm already on the latest version of cffi.
This is interesting from the cffi documentation: "Python 3 on Windows: ffi.dlopen(None) does not work. This problem is messy and not really fixable. The problem does not occur if you try to call a function from a specific DLL that exists on your system: then you use ffi.dlopen("path.dll")." https://cffi.readthedocs.io/en/latest/overview.html#main-mode-of-usage However i'm using python 2.7
It's interesting though, that dlopen(None) actually works when you use the scripting api directly, but not when you go via this precompiled backend or whatever this is meant to be. Either way looks like you might need a workaround at the very least for python 3, as according to the documentation it's not supposed to work anyway.
I know that dlopen(None)
is not supposed to work on Windows.
But I expected an exception to be thrown instead of crashing the Python interpreter.
Pure Python code should never crash, so there must be a bug somewhere, probably in CFFI or in one of its dependencies.
I've asked about this on the CFFI mailing list: https://groups.google.com/g/python-cffi/c/5DgTyV0DAas
In the meantime, you could try whether the crash also happens with older CFFI versions.
Of course pure python code should not crash the interpreter, but in this case we are not dealing with a pure python code, we are dealing with a precompiled dll (_cffi_backend.pyd) so it is completely reasonable that it might crash the interpreter. In this case it must be either A) a bug the precompiled code or B) a binary incompatibility between the precompiled code and my system. The suggestion in the mailing list reply seems reasonable - I've seen NULL pointer into "%s" crash before.
On a side note, if you know that dlopen(None) is not supposed to work on windows, but sounddevice still calls it, then clearly it is expected to do nothing and another workaround would be to simply not call it on windows. Assuming this, I've replaced the line with raise OSError()
and I can now use sounddevice.
For what it's worth, I get OSError: cannot load library '<None>': error 0x57
(no crashes) from both of the first two test cases above.
Python 2.7.15 (v2.7.15:ca079a3ea3, Apr 30 2018, 16:30:26) [MSC v.1500 64 bit (AMD64)] on win32
cffi==1.12.3
Windows 10 Pro 1903
But it makes sense to just add a check to bypass that path if it is not supposed to work on windows.
Here's Armin's answer from the mailing list:
Thanks, I've added some explicit checks. Note that I couldn't reproduce on my Windows 10 machine, where it ends with a clean OSError but with a somewhat obscure error message. Maybe the difference is that I tried with a version compiled on my own, and the automatic builders make a version that is linked with a different libc. The error message is formatted with "%s" but in this case the pointer is NULL. Maybe that causes only some of the versions of libc to crash... Anyway, I've added a check and complain explicitly now before even trying to call the Windows LoadLibrary() API.
The check he mentioned is here: https://foss.heptapod.net/pypy/cffi/-/commit/0c0a5c48f034a3bc191563c2d504f0a8d66797a4
BTW, @ileben and @daanzu, since both of you seem to be using Python 2.7: Python 2.x support will be dropped with the next release of the sounddevice
module.
@mgeier Fair enough. Thanks for the heads up, and for the great package.
A few weeks ago it was working well to me, then now is coming out this issue. The significant change I had since then.. I opted -in to Windows Insider's builds, which upgrades the windows version.
Not just sounddevice, but pyaudio also stops python process without any saying.
But that happens only if I installed by pip
.
If I use miniconda, there I install by conda install -c conda-forge python-sounddevice
, also conda install pyaudio
, then both works.
The difference between conda an pypi distributions is that in conda distributions the underlaying PortAudio is not built into the packages. Most likely the problem is in PortAudio, the ASIO part and that is related to the Windows version which will came out in April-Mai.
My environment has multiple ASIO drivers, since I am using for music production. I cannot tell that more concretely it is related to this or this specific driver, but since I know I must use conda with the upcoming Windows version, I have to do so until PortAudio is fixed.