Commit graph

8540 commits

Author SHA1 Message Date
Barnabás Pőcze
616519d704 spa: support: loop: assert loop is not polling when source is removed
`spa_source`s whose backing storage is not managed by the loop
cannot be safely removed while the loop is polling.
Assert that it does not happen.
2022-03-06 18:40:43 +00:00
Barnabás Pőcze
60b9d9081b spa: only remove embedded source from data loop from within the loop
Use `spa_loop_invoke()` to invoke a callback on the data loop
to remove an embedded `spa_source` from the data loop.

Embedded `spa_source` objects cannot be safely removed
while the loop is polling without risking potential
use-after-frees.
2022-03-06 18:40:43 +00:00
Barnabás Pőcze
7647ea7c83 spa: support: loop: fix use-after-free when loop is reentered
The core of the issue is the following: what happens if an
active source is destroyed before it could be dispatched?

For loop-managed sources (`struct source_impl`) this was addressed
by storing all destroyed sources in a list, and only freeing them
after dispatching has been finished. (0eb73f0f06)
This approach works for both strictly single-threaded
and `pw_thread_loop` loops assuming the loop is not
reentered.

However, if the loop is reentered, there can still be issues.
Assume that in one iteration sources A and B are active,
and returned from the system call, and source B is destroyed
before the loop starts dispatching. Consider what happens when
"A" is dispatched first, and it reenters the loop with timeout 0.
Imagine there are no new events, so `loop_iterate()` will immediately
return, but it will first destroy everything in the destroy list
(this is done at the end of `loop_iterate()`).
And herein lies the problem. In the previous iteration,
there exists a `spa_poll_event` object which points to source "B",
but that has just been destroyed at the end of the recursive
iteration. This will trigger a use-after-free once the previous
iteration inspects it.

Fix that by processing the destroy list right after first
processing the returned `spa_poll_event` objects, and
"detach" the source from the loop and its iterations
in `process_destroy()` before the source is destroyed.

See #2114 #2147
2022-03-06 18:40:43 +00:00
Barnabás Pőcze
529b6fd1b8 test: loop: add test which destroys managed source before reentering
Add a test which triggers two event sources in the loop's "before"
control hook, and destroys the second source in the loop's "after"
control hook, and then reenters the loop in the event handler of
the first source. At the moment, this test triggers a use-after-free.

==2973914==ERROR: AddressSanitizer: heap-use-after-free on address 0x608000000440 [...]
READ of size 4 at 0x608000000440 thread T0
    #0 0x7fa97f60c6b7 in loop_iterate ../spa/plugins/support/loop.c:376
    #1 0x7fa98472c1eb in pw_main_loop_run ../src/pipewire/main-loop.c:148
    #2 0x559995af7a76 in destroy_managed_source_before_dispatch_recurse ../test/test-loop.c:355
    #3 0x559995b02678 in start_test_nofork ../test/pwtest.c:882
    #4 0x559995b06191 in run_test ../test/pwtest.c:1087
    #5 0x559995b0948a in run_tests ../test/pwtest.c:1283
    #6 0x559995b0aea4 in main ../test/pwtest.c:1482
    #7 0x7fa98360130f in __libc_start_call_main (/usr/lib/libc.so.6+0x2d30f)
    #8 0x7fa9836013c0 in __libc_start_main@GLIBC_2.2.5 (/usr/lib/libc.so.6+0x2d3c0)
    #9 0x559995aed754 in _start (/home/pb/temp/src/pipewire/build/test/test-loop+0x26754)

0x608000000440 is located 32 bytes inside of 96-byte region [0x608000000420,0x608000000480)
freed by thread T0 here:
    #0 0x7fa984ffda79 in __interceptor_free /usr/src/debug/gcc/libsanitizer/asan/asan_malloc_linux.cpp:127
    #1 0x7fa97f60b03a in process_destroy ../spa/plugins/support/loop.c:344
    #2 0x7fa97f60cbf8 in loop_iterate ../spa/plugins/support/loop.c:387
    #3 0x559995af5b62 in dmsbd_recurse_on_event ../test/test-loop.c:298
    #4 0x7fa97f60d826 in source_io_func ../spa/plugins/support/loop.c:396
    #5 0x7fa97f60c7e7 in loop_iterate ../spa/plugins/support/loop.c:377
    #6 0x7fa98472c1eb in pw_main_loop_run ../src/pipewire/main-loop.c:148
    #7 0x559995af7a76 in destroy_managed_source_before_dispatch_recurse ../test/test-loop.c:355
    #8 0x559995b02678 in start_test_nofork ../test/pwtest.c:882
    #9 0x559995b06191 in run_test ../test/pwtest.c:1087
    #10 0x559995b0948a in run_tests ../test/pwtest.c:1283
    #11 0x559995b0aea4 in main ../test/pwtest.c:1482
    #12 0x7fa98360130f in __libc_start_call_main (/usr/lib/libc.so.6+0x2d30f)

previously allocated by thread T0 here:
    #0 0x7fa984ffdfb9 in __interceptor_calloc /usr/src/debug/gcc/libsanitizer/asan/asan_malloc_linux.cpp:154
    #1 0x7fa97f60d883 in loop_add_io ../spa/plugins/support/loop.c:408
    #2 0x559995af75de in destroy_managed_source_before_dispatch_recurse ../test/test-loop.c:349
    #3 0x559995b02678 in start_test_nofork ../test/pwtest.c:882
    #4 0x559995b06191 in run_test ../test/pwtest.c:1087
    #5 0x559995b0948a in run_tests ../test/pwtest.c:1283
    #6 0x559995b0aea4 in main ../test/pwtest.c:1482
    #7 0x7fa98360130f in __libc_start_call_main (/usr/lib/libc.so.6+0x2d30f)

SUMMARY: AddressSanitizer: heap-use-after-free ../spa/plugins/support/loop.c:376 in loop_iterate
2022-03-06 18:40:43 +00:00
Barnabás Pőcze
b1c189fa86 test: rewrite test which destroys active source before dispatching
Rewrite the test that destroys an active managed source
right after polling is done. There is no need to use a
thread loop because the same thing can be simulated using
the before/after loop control hooks in a more controlled
manner.
2022-03-06 18:40:43 +00:00
Barnabás Pőcze
2eb36c00c1 spa: support: loop: add polling flag
Store whether or not the loop is currently polling, i.e.
calling `spa_system_pollfd_wait()`.
2022-03-06 18:40:43 +00:00
Barnabás Pőcze
4ed0365976 spa: support: loop: assert source type 2022-03-06 18:40:43 +00:00
Barnabás Pőcze
cfc8510ce8 spa: support: loop: add some invariant assertions 2022-03-06 18:40:43 +00:00
Barnabás Pőcze
55ee5ec8b2 spa: support: loop: rename variables
It may be a little confusing that both the loop object
and the `source_impl` objects are referred to with variables
named `impl`. For this reason, rename all source_impl objects
named `impl` to `s`.
2022-03-06 18:40:43 +00:00
Barnabás Pőcze
a4e7042176 spa: support: loop: do not return early in case of an error
It is expected that `nfds` is non-negative in the vast majority
of cases, so hopefully the runtime performance will not be
significantly affected by removing the check. This way
it is guaranteed that the destroy list is processed.
2022-03-06 18:40:43 +00:00
Barnabás Pőcze
275e23a34d spa: support: loop: print previous mask when updating
Print the previous event mask in `loop_update_io()`
as well as the new one.
2022-03-06 18:40:43 +00:00
Barnabás Pőcze
8941fc2866 spa: support: loop: get array size using macro 2022-03-06 18:40:43 +00:00
Barnabás Pőcze
cb8c2d8857 spa: support: loop: reset rmask after dispatch
Reset the `rmask` of the sources to zero after
dispatching the callbacks. This way the sources
are always as up-to-date as possible.
2022-03-06 18:40:43 +00:00
Barnabás Pőcze
a22ce76dbf spa: support: loop: initialize rmask
Set `rmask` to zero when a source is added to,
or removed from the loop.
2022-03-06 18:40:43 +00:00
Barnabás Pőcze
e2287f35db spa: support: loop: move struct members
Move the boolean members of `struct source_impl` to the end
of the struct. This changes the size of the struct from
104 bytes to 96 bytes on x86-64.

Before:

struct source_impl {
        struct spa_source          source;               /*     0    48 */
        struct impl *              impl;                 /*    48     8 */
        struct spa_list            link;                 /*    56    16 */
        /* --- cacheline 1 boundary (64 bytes) was 8 bytes ago --- */
        _Bool                      close;                /*    72     1 */

        /* XXX 7 bytes hole, try to pack */

        union {
                spa_source_io_func_t io;                 /*    80     8 */
                spa_source_idle_func_t idle;             /*    80     8 */
                spa_source_event_func_t event;           /*    80     8 */
                spa_source_timer_func_t timer;           /*    80     8 */
                spa_source_signal_func_t signal;         /*    80     8 */
        } func;                                          /*    80     8 */
        _Bool                      enabled;              /*    88     1 */

        /* XXX 7 bytes hole, try to pack */

        struct spa_source *        fallback;             /*    96     8 */

        /* size: 104, cachelines: 2, members: 7 */
        /* sum members: 90, holes: 2, sum holes: 14 */
        /* last cacheline: 40 bytes */
};

After:

struct source_impl {
        struct spa_source          source;               /*     0    48 */
        struct impl *              impl;                 /*    48     8 */
        struct spa_list            link;                 /*    56    16 */
        /* --- cacheline 1 boundary (64 bytes) was 8 bytes ago --- */
        union {
                spa_source_io_func_t io;                 /*    72     8 */
                spa_source_idle_func_t idle;             /*    72     8 */
                spa_source_event_func_t event;           /*    72     8 */
                spa_source_timer_func_t timer;           /*    72     8 */
                spa_source_signal_func_t signal;         /*    72     8 */
        } func;                                          /*    72     8 */
        struct spa_source *        fallback;             /*    80     8 */
        _Bool                      close;                /*    88     1 */
        _Bool                      enabled;              /*    89     1 */

        /* size: 96, cachelines: 2, members: 7 */
        /* padding: 6 */
        /* last cacheline: 32 bytes */
};
2022-03-06 18:40:43 +00:00
Barnabás Pőcze
1e99551233 test: loop: do not use NULL as event handler 2022-03-06 18:40:43 +00:00
Pauli Virtanen
67a27d80c6 gst: use target.object instead of node.target, soft-deprecate ids
Use target-object=<serial/name> instead of path=<id> for specifying
sink/src targets. Deprecate path= argument.

Change device provider to preferably expose serials instead of ids.
2022-03-06 18:34:47 +00:00
Pauli Virtanen
d66e9f1ae1 bluez5: a2dp-sink: stop flushing if source was removed
The flush source gets removed on I/O error. We should not continue
flushing after that.
2022-03-06 16:47:25 +02:00
Pauli Virtanen
7ade8fa8fb pwtest: fix daemon log scrambling
Nonblocking pipes can scramble logs if we read too slow, so use max size
buffers.

Also use CLOEXEC for the pipes to be safer, and minor other fixes.
2022-03-06 02:29:35 +02:00
Pauli Virtanen
8673f8c03d pwtest: shorter default timeout 2022-03-05 17:51:22 +00:00
Pauli Virtanen
9cb55852f4 CI: add functional test program deps 2022-03-05 17:51:22 +00:00
Pauli Virtanen
f3831da67a pwtest: ARG_DAEMON tests don't work on valgrind 2022-03-05 17:51:22 +00:00
Pauli Virtanen
c604f1608a test: add simple functional tests
Try running openal-info.
2022-03-05 17:51:22 +00:00
Pauli Virtanen
76bab25afb pwtest: handle SIGTERM/SIGINT in runner
Catch SIGTERM/SIGINT in test runner, and clean up any spawned processes.

Fixes printing test output on termination by signal (e.g. meson
timeout), and doesn't leave spawned processes running.
2022-03-05 17:51:22 +00:00
Pauli Virtanen
ad3c90dbb9 pwtest: use default debug level 4 for spawned daemons 2022-03-05 17:51:22 +00:00
Pauli Virtanen
a7bd52d07d pwtest/Makefile: set SPA_DATA_DIR 2022-03-05 17:51:22 +00:00
Pauli Virtanen
581f6c7f1d pwtest: add pwtest_spawn for running external programs 2022-03-05 17:51:22 +00:00
Pauli Virtanen
df4f844daa pwtest: ensure all spawned daemons are terminated
Set process group, and send signal to them all.
2022-03-05 17:51:22 +00:00
Pauli Virtanen
24fd273820 bluez5: backend-ofono: don't do codec probe connections + add wait
Codec probe connections can trigger bad behavior from oFono if done when
device is busy (e.g. at connect), and they might be done at the same
time as A2DP transport is acquired which cannot work.

Also, oFono will not reply to DBus Acquire, if device does not complete
codec negotiation correctly. This is most likely to happen just after
device connect, when it is busy with other stuff (eg A2DP).

Remove codec probe connections altogether: instead, we guess mSBC if
mSBC is enabled and otherwise CVSD. If the guess turns out to be wrong,
which is unlikely (almost all devices have mSBC), we recreate the
transport with correct codec (from main loop, must not be done in
*_acquire because that can destroy nodes + unload the spa libs while
we're being called from there).

To avoid oFono DBus hangs at startup, add delay before marking the
profile connected, enforcing a time difference to A2DP operations.
2022-03-05 17:46:40 +00:00
Michael D
8026b65caa Update meson.build
(cherry picked from commit 8da11c3853cb7a19cd267ad94de591f88461d31a)
2022-03-05 00:37:25 +00:00
Michael D
eec017f245 Update man/pw-top.1.rst.in 2022-03-04 22:43:51 +00:00
Wim Taymans
1647c169b2 alsa: improve latency update 2022-03-04 17:21:17 +01:00
Wim Taymans
bcdd1ea811 alsa: set better ranges on properties 2022-03-04 17:21:14 +01:00
Wim Taymans
c7de69eac7 channelmix: improve disabled flag
Also parse updates to the disabled flag when disabled so that we can
enabled it again.
2022-03-04 17:21:11 +01:00
Wim Taymans
2653e9f129 filter-chain: use property hints
Use property hints to expose int or bool controls.
2022-03-03 21:23:25 +01:00
Wim Taymans
2125ec048d filter-chain: use dynamic builder for param update 2022-03-03 21:22:23 +01:00
Wim Taymans
8646117374 stream: guard against NULL params 2022-03-03 21:21:43 +01:00
Wim Taymans
c03850fd76 merger: also remove PropInfo
We use the PropInfo from the channelmixer.
2022-03-03 19:46:33 +01:00
Wim Taymans
a6304b47f6 pw-cat: improve DSD file reading
Support reading non-multiples of the blocksize.
Stop reading at the end of the file.
2022-03-03 16:05:03 +01:00
Wim Taymans
ce2f1b3737 dsffile: fix negative interleave 2022-03-03 14:01:32 +01:00
Wim Taymans
d25bb89cc0 channelmix: enable upmixing by default, disable normalization 2022-03-03 12:33:02 +01:00
Wim Taymans
5a55e1a47a pulse-server: handle pulse.properties
Load properties from pulse.properties section so that they can have
overrides.
2022-03-03 11:59:55 +01:00
Wim Taymans
6c4d3a5158 0.3.48 2022-03-03 11:30:56 +01:00
Wim Taymans
b645793d7e filter-chain: remove stray debug 2022-03-02 21:43:37 +01:00
Wim Taymans
b7c78d0108 minimal.conf: add some more example config
Add an example for how to add a virtual source and how to link it
to the real source.

Fixes #2105
2022-03-02 12:20:44 +01:00
Wim Taymans
99f9f729ff handle open_memstream errors
Fixes #2182
2022-03-02 11:48:31 +01:00
Wim Taymans
fdaf4613d8 module-raop: handle and debug read errors
Fixes #2183
2022-03-02 11:28:43 +01:00
Wim Taymans
00d4de3799 module-raop: use the right socket to read from
See #2183
2022-03-02 11:24:40 +01:00
Wim Taymans
e7958fac1b filter-chain: remove limits on ports
Allocate all ports dynamically so that there is no limit anymore.

Fixes #2179
2022-03-02 10:12:22 +01:00
Wim Taymans
c89595d86f protocol: increase some limits 2022-03-02 10:05:27 +01:00