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

python -m sounddevice crashes the python.exe process #256

Open
ileben opened this issue Jul 4, 2020 · 16 comments
Open

python -m sounddevice crashes the python.exe process #256

ileben opened this issue Jul 4, 2020 · 16 comments

Comments

@ileben
Copy link

ileben commented Jul 4, 2020

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.

@mgeier
Copy link
Member

mgeier commented Jul 5, 2020

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)

@ileben
Copy link
Author

ileben commented Jul 6, 2020

<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.

@mgeier
Copy link
Member

mgeier commented Jul 6, 2020

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)

@ileben
Copy link
Author

ileben commented Jul 6, 2020

Crashes in the exact same way.

@mgeier
Copy link
Member

mgeier commented Jul 6, 2020

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)?

@ileben
Copy link
Author

ileben commented Jul 6, 2020

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).

@ileben
Copy link
Author

ileben commented Jul 6, 2020

I'm already on the latest version of cffi.

@ileben
Copy link
Author

ileben commented Jul 6, 2020

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

@ileben
Copy link
Author

ileben commented Jul 6, 2020

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.

@mgeier
Copy link
Member

mgeier commented Jul 6, 2020

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.

@ileben
Copy link
Author

ileben commented Jul 6, 2020

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.

@daanzu
Copy link

daanzu commented Jul 7, 2020

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.

@mgeier
Copy link
Member

mgeier commented Jul 7, 2020

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

@mgeier
Copy link
Member

mgeier commented Jul 7, 2020

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.

@daanzu
Copy link

daanzu commented Jul 7, 2020

@mgeier Fair enough. Thanks for the heads up, and for the great package.

@tiborkiss
Copy link

tiborkiss commented Mar 29, 2021

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.

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

No branches or pull requests

4 participants