LCAV / pyroomacoustics

Pyroomacoustics is a package for audio signal processing for indoor applications. It was developed as a fast prototyping platform for beamforming algorithms in indoor scenarios.

Home Page:https://pyroomacoustics.readthedocs.io

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Segfault in `simul_ray()`

NicolasHug opened this issue · comments

The following snippet throws a segfault (sometimes) on a few linux machines that I've tried:

import pyroomacoustics as pra

room_dim = [30, 30]
source = [2, 3]
mic_array = [[8], [8]]

room = pra.ShoeBox(
    room_dim,
    ray_tracing=True,
    materials=pra.Material(energy_absorption=.1, scattering=.2),
    air_absorption=False,
    max_order=0,
)
room.add_microphone_array(mic_array)
room.add_source(source)
room.set_ray_tracing(n_rays=10_000)
room.compute_rir()

Strangely, I'm getting a segfault perhaps 1/3 of the time. It works and runs fine otherwise. I tried building from source (a few days ago) and observed the same segfault.

Perhaps my snippet is doing something wrong? Thanks!

CC @nateanl


Env: Just ran conda create -n pra python=3.9 and pip install pyroomacoustics

(pra) ➜  ~ pip freeze
certifi @ file:///croot/certifi_1665076670883/work/certifi
Cython==0.29.32
numpy==1.23.5
pybind11==2.10.1
pyroomacoustics==0.7.2
scipy==1.9.3
(pra) ➜  ~ python --version
Python 3.9.15

gdb backtrace (not super useful as-is, all it says it that the segfault happened in Room<2ul>::simul_ray):

(pra) ➜  ~ gdb python
GNU gdb (GDB) Fedora 11.1-5.fc34
Copyright (C) 2021 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "x86_64-redhat-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<https://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
    <http://www.gnu.org/software/gdb/documentation/>.

For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from python...


(gdb) run pra.py
Starting program: /home/nicolashug/.miniconda3/envs/pra/bin/python pra.py
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib64/libthread_db.so.1".
Missing separate debuginfo for /home/nicolashug/.miniconda3/envs/pra/lib/python3.9/site-packages/numpy/core/../../numpy.libs/libgfortran-040039e1.so.5.0.0
Try: dnf --enablerepo='*debug*' install /usr/lib/debug/.build-id/5b/be74eb6855e0a2c043c0bec2f484bf3e9f14c0.debug
Missing separate debuginfo for /home/nicolashug/.miniconda3/envs/pra/lib/python3.9/site-packages/numpy/core/../../numpy.libs/libquadmath-96973f99.so.0.0.0
Try: dnf --enablerepo='*debug*' install /usr/lib/debug/.build-id/54/9b4c82347785459571c79239872ad31509dcf4.debug
[New Thread 0x7fffe77e6640 (LWP 141388)]
[New Thread 0x7fffe6fe5640 (LWP 141389)]
[New Thread 0x7fffe27e4640 (LWP 141390)]
[New Thread 0x7fffdffe3640 (LWP 141391)]
[New Thread 0x7fffdd7e2640 (LWP 141392)]
[New Thread 0x7fffdafe1640 (LWP 141393)]
[New Thread 0x7fffd87e0640 (LWP 141394)]
[New Thread 0x7fffd313d640 (LWP 141395)]
[New Thread 0x7fffd293c640 (LWP 141396)]
[New Thread 0x7fffce13b640 (LWP 141397)]
[New Thread 0x7fffcb93a640 (LWP 141398)]
[New Thread 0x7fffc9139640 (LWP 141399)]
[New Thread 0x7fffc6938640 (LWP 141400)]
[New Thread 0x7fffc4137640 (LWP 141401)]

Thread 1 "python" received signal SIGSEGV, Segmentation fault.
0x00007fffbe4146be in Room<2ul>::simul_ray(float, float, Eigen::Matrix<float, 2, 1, 0, 2, 1>, float) () from /home/nicolashug/.miniconda3/envs/pra/lib/python3.9/site-packages/pyroomacoustics/libroom.cpython-39-x86_64-linux-gnu.so
Missing separate debuginfos, use: dnf debuginfo-install glibc-2.33-21.fc34.x86_64


(gdb) backtrace
#0  0x00007fffbe4146be in Room<2ul>::simul_ray(float, float, Eigen::Matrix<float, 2, 1, 0, 2, 1>, float) ()
   from /home/nicolashug/.miniconda3/envs/pra/lib/python3.9/site-packages/pyroomacoustics/libroom.cpython-39-x86_64-linux-gnu.so
#1  0x00007fffbe414c08 in Room<2ul>::ray_tracing(unsigned long, Eigen::Matrix<float, 2, 1, 0, 2, 1>) ()
   from /home/nicolashug/.miniconda3/envs/pra/lib/python3.9/site-packages/pyroomacoustics/libroom.cpython-39-x86_64-linux-gnu.so
#2  0x00007fffbe427937 in pybind11::cpp_function::initialize<pybind11::cpp_function::initialize<void, Room<2ul>, unsigned long, Eigen::Matrix<float, 2, 1, 0, 2, 1>, pybind11::name, pybind11::is_method, pybind11::sibling>(void (Room<2ul>::*)(unsigned long, Eigen::Matrix<float, 2, 1, 0, 2, 1>), pybind11::name const&, pybind11::is_method const&, pybind11::sibling const&)::{lambda(Room<2ul>*, unsigned long, Eigen::Matrix<float, 2, 1, 0, 2, 1>)#1}, void, Room<2ul>*, unsigned long, Eigen::Matrix<float, 2, 1, 0, 2, 1>, pybind11::name, pybind11::is_method, pybind11::sibling>(pybind11::cpp_function::initialize<void, Room<2ul>, unsigned long, Eigen::Matrix<float, 2, 1, 0, 2, 1>, pybind11::name, pybind11::is_method, pybind11::sibling>(void (Room<2ul>::*)(unsigned long, Eigen::Matrix<float, 2, 1, 0, 2, 1>), pybind11::name const&, pybind11::is_method const&, pybind11::sibling const&)::{lambda(Room<2ul>*, unsigned long, Eigen::Matrix<float, 2, 1, 0, 2, 1>)#1}&&, void (*)(Room<2ul>*, unsigned long, Eigen::Matrix<float, 2, 1, 0, 2, 1>), pybind11::name const&, pybind11::is_method const&, pybind11::sibling const&)::{lambda(pybind11::detail::function_call&)#3}::_FUN(pybind11::detail::function_call&) ()
   from /home/nicolashug/.miniconda3/envs/pra/lib/python3.9/site-packages/pyroomacoustics/libroom.cpython-39-x86_64-linux-gnu.so
#3  0x00007fffbe3fc238 in pybind11::cpp_function::dispatcher(_object*, _object*, _object*) ()
   from /home/nicolashug/.miniconda3/envs/pra/lib/python3.9/site-packages/pyroomacoustics/libroom.cpython-39-x86_64-linux-gnu.so
#4  0x0000000000507457 in cfunction_call (func=0x7fffbe489590, args=<optimized out>, kwargs=<optimized out>)
    at /usr/local/src/conda/python-3.9.15/Objects/methodobject.c:543
#5  0x00000000004f068c in _PyObject_MakeTpCall (tstate=0x76bc30, callable=0x7fffbe489590, args=<optimized out>, 
    nargs=<optimized out>, keywords=0x0) at /usr/local/src/conda/python-3.9.15/Objects/call.c:191
#6  0x0000000000505390 in _PyObject_VectorcallTstate (kwnames=0x0, nargsf=<optimized out>, args=0x7fffbe33f1e0, 
    callable=0x7fffbe489590, tstate=0x76bc30) at /usr/local/src/conda/python-3.9.15/Include/cpython/abstract.h:116
#7  _PyObject_VectorcallTstate (kwnames=0x0, nargsf=<optimized out>, args=0x7fffbe33f1e0, callable=0x7fffbe489590, 
    tstate=0x76bc30) at /usr/local/src/conda/python-3.9.15/Include/cpython/abstract.h:103
#8  method_vectorcall (method=<optimized out>, args=0x7fffbe33f1e8, nargsf=<optimized out>, kwnames=0x0)
    at /usr/local/src/conda/python-3.9.15/Objects/classobject.c:53
#9  0x00000000004ec4d4 in _PyObject_VectorcallTstate (kwnames=0x0, nargsf=<optimized out>, args=0x7fffbe33f1e8, 
--Type <RET> for more, q to quit, c to continue without paging--
    callable=0x7fffbe48aa40, tstate=0x76bc30) at /usr/local/src/conda/python-3.9.15/Include/cpython/abstract.h:118
#10 PyObject_Vectorcall (kwnames=0x0, nargsf=<optimized out>, args=0x7fffbe33f1e8, callable=0x7fffbe48aa40)
    at /usr/local/src/conda/python-3.9.15/Include/cpython/abstract.h:127
#11 call_function (kwnames=0x0, oparg=<optimized out>, pp_stack=<synthetic pointer>, tstate=0x76bc30)
    at /usr/local/src/conda/python-3.9.15/Python/ceval.c:5077
#12 _PyEval_EvalFrameDefault (tstate=<optimized out>, f=0x7fffbe33f040, throwflag=<optimized out>)
    at /usr/local/src/conda/python-3.9.15/Python/ceval.c:3489
#13 0x00000000004f7f33 in _PyEval_EvalFrame (throwflag=0, f=0x7fffbe33f040, tstate=0x76bc30)
    at /usr/local/src/conda/python-3.9.15/Include/internal/pycore_ceval.h:40
#14 function_code_fastcall (tstate=0x76bc30, co=<optimized out>, args=<optimized out>, nargs=<optimized out>, 
    globals=0x7fffbe398a40) at /usr/local/src/conda/python-3.9.15/Objects/call.c:330
#15 0x00000000004e7e29 in _PyObject_VectorcallTstate (kwnames=0x0, nargsf=<optimized out>, args=0x15db1e0, 
    callable=0x7fffbe337c10, tstate=0x76bc30) at /usr/local/src/conda/python-3.9.15/Include/cpython/abstract.h:118
#16 PyObject_Vectorcall (kwnames=0x0, nargsf=<optimized out>, args=0x15db1e0, callable=0x7fffbe337c10)
    at /usr/local/src/conda/python-3.9.15/Include/cpython/abstract.h:127
#17 call_function (kwnames=0x0, oparg=<optimized out>, pp_stack=<synthetic pointer>, tstate=0x76bc30)
    at /usr/local/src/conda/python-3.9.15/Python/ceval.c:5077
#18 _PyEval_EvalFrameDefault (tstate=<optimized out>, f=0x15daf20, throwflag=<optimized out>)
    at /usr/local/src/conda/python-3.9.15/Python/ceval.c:3506
#19 0x00000000004f7f33 in _PyEval_EvalFrame (throwflag=0, f=0x15daf20, tstate=0x76bc30)
    at /usr/local/src/conda/python-3.9.15/Include/internal/pycore_ceval.h:40
#20 function_code_fastcall (tstate=0x76bc30, co=<optimized out>, args=<optimized out>, nargs=<optimized out>, 
    globals=0x7fffbe398a40) at /usr/local/src/conda/python-3.9.15/Objects/call.c:330
#21 0x00000000004e7e29 in _PyObject_VectorcallTstate (kwnames=0x0, nargsf=<optimized out>, args=0x7c9230, 
    callable=0x7fffbe337ca0, tstate=0x76bc30) at /usr/local/src/conda/python-3.9.15/Include/cpython/abstract.h:118
#22 PyObject_Vectorcall (kwnames=0x0, nargsf=<optimized out>, args=0x7c9230, callable=0x7fffbe337ca0)
    at /usr/local/src/conda/python-3.9.15/Include/cpython/abstract.h:127
#23 call_function (kwnames=0x0, oparg=<optimized out>, pp_stack=<synthetic pointer>, tstate=0x76bc30)
    at /usr/local/src/conda/python-3.9.15/Python/ceval.c:5077
#24 _PyEval_EvalFrameDefault (tstate=<optimized out>, f=0x7c90c0, throwflag=<optimized out>)
    at /usr/local/src/conda/python-3.9.15/Python/ceval.c:3506
#25 0x00000000004e689a in _PyEval_EvalFrame (throwflag=0, f=0x7c90c0, tstate=0x76bc30)
    at /usr/local/src/conda/python-3.9.15/Include/internal/pycore_ceval.h:40
--Type <RET> for more, q to quit, c to continue without paging--
#26 _PyEval_EvalCode (tstate=<optimized out>, _co=<optimized out>, globals=<optimized out>, locals=<optimized out>, 
    args=<optimized out>, argcount=<optimized out>, kwnames=0x0, kwargs=0x0, kwcount=<optimized out>, kwstep=2, 
    defs=0x0, defcount=<optimized out>, kwdefs=0x0, closure=0x0, name=0x0, qualname=0x0)
    at /usr/local/src/conda/python-3.9.15/Python/ceval.c:4329
#27 0x00000000004e6527 in _PyEval_EvalCodeWithName (_co=<optimized out>, globals=<optimized out>, 
    locals=<optimized out>, args=<optimized out>, argcount=<optimized out>, kwnames=<optimized out>, kwargs=0x0, 
    kwcount=0, kwstep=2, defs=0x0, defcount=0, kwdefs=0x0, closure=0x0, name=0x0, qualname=0x0)
    at /usr/local/src/conda/python-3.9.15/Python/ceval.c:4361
#28 0x00000000004e64d9 in PyEval_EvalCodeEx (_co=<optimized out>, globals=<optimized out>, locals=<optimized out>, 
    args=<optimized out>, argcount=<optimized out>, kws=<optimized out>, kwcount=0, defs=0x0, defcount=0, kwdefs=0x0, 
    closure=0x0) at /usr/local/src/conda/python-3.9.15/Python/ceval.c:4377
#29 0x000000000059329b in PyEval_EvalCode (co=co@entry=0x7fffea5fb5b0, globals=globals@entry=0x7fffea66e040, 
    locals=locals@entry=0x7fffea66e040) at /usr/local/src/conda/python-3.9.15/Python/ceval.c:828
#30 0x00000000005c0ad7 in run_eval_code_obj (tstate=0x76bc30, co=0x7fffea5fb5b0, globals=0x7fffea66e040, 
    locals=0x7fffea66e040) at /usr/local/src/conda/python-3.9.15/Python/pythonrun.c:1221
#31 0x00000000005bcb00 in run_mod (mod=<optimized out>, filename=<optimized out>, globals=0x7fffea66e040, 
    locals=0x7fffea66e040, flags=<optimized out>, arena=<optimized out>)
    at /usr/local/src/conda/python-3.9.15/Python/pythonrun.c:1242
#32 0x00000000004566f4 in pyrun_file (fp=<optimized out>, filename=<optimized out>, start=<optimized out>, 
    globals=<optimized out>, locals=<optimized out>, closeit=<optimized out>, flags=0x7fffffffdba8)
    at /usr/local/src/conda/python-3.9.15/Python/pythonrun.c:1140
#33 0x00000000005b67e2 in pyrun_simple_file (flags=0x7fffffffdba8, closeit=1, filename=0x7fffea5a1df0, fp=0x76b8a0)
    at /usr/local/src/conda/python-3.9.15/Python/pythonrun.c:450
#34 PyRun_SimpleFileExFlags (fp=0x76b8a0, filename=<optimized out>, closeit=1, flags=0x7fffffffdba8)
    at /usr/local/src/conda/python-3.9.15/Python/pythonrun.c:483
#35 0x00000000005b3d5e in pymain_run_file (cf=0x7fffffffdba8, config=0x76c7a0)
    at /usr/local/src/conda/python-3.9.15/Modules/main.c:379
#36 pymain_run_python (exitcode=0x7fffffffdba0) at /usr/local/src/conda/python-3.9.15/Modules/main.c:604
#37 Py_RunMain () at /usr/local/src/conda/python-3.9.15/Modules/main.c:683
#38 0x0000000000587349 in Py_BytesMain (argc=<optimized out>, argv=<optimized out>)
    at /usr/local/src/conda/python-3.9.15/Modules/main.c:1129
#39 0x00007ffff7c91b75 in __libc_start_main () from /lib64/libc.so.6
#40 0x00000000005871fe in _start ()
(gdb) 

I think the issue is from the mic_array definition, it should be a list of lists where each sub-list has D elements depending on the room dimension (2 or 3). The number of sub-lists is the number of microphones.
You can try with mic_array = [[8, 8], [9, 9]] which means there are two microphones and the coordinates of the microphones are (8, 8) and (9, 9), respectively. The segfault issue should be gone.

sorry, the explanation above is wrong. micarray should be a list of list, where the first dimension is D (the room dimension), and the second dimension is the number of microphones.
You can try mic_array = [[8,], [8,]], and see if that helps?

okay, I run the code three times, and two of them also failed... will look into it.

Note that I'm still getting a segfault when using room.add_microphone([8, 8]) (i.e. using add_micrphone() instead of add_microphone_array())

@NicolasHug Thanks for reporting this, I will look into it. Even if the input is not correctly formatted, a seg fault is not a desirable behavior !

Not sure how useful this is but I have added a test in CI. Here's the result. It seems a little bit random... I run the example above 30 times (in a loop). So if each fails with prob. 1/3, then all tests succeed only with prob < 10 ** (-5)

https://github.com/LCAV/pyroomacoustics/actions/runs/3607163056/jobs/6078998381

image

After some more testing, it seems to occur only for 2D simulation when scattering != 0. This should narrow the bug to the scat_ray function. I suspect this may be a case where some function expects a 3D vector but is passed a 2D one. I will investigate a little bit more.

@NicolasHug @nateanl I could track down the bug to the Room::next_wall_hit method that was hardcoded for 3D rooms in the shoebox case. I have made a fix in PR #294 and will release this as soon as possible. The fix is done at line 665 or room.cpp.

Thank you very much for the fix @fakufaku !

BTW I've been porting the PRA's ray_tracing method to torchaudio (pytorch/audio#2850) and I found the PRA code to be very clear, well document and easy to follow. It made my job a lot easier. Thank you!

@NicolasHug And thank you for finding it 😄 The fix is available in v0.7.3 on pypi.

Thanks for the kind words, there are many parts I wish were more polished though... Especially in the C++ part... 🙈