The `impl::servers` list contains all servers, and they are all
destroyed in `impl_clear()`. However, by that time, modules were
not freed previously, so if there were any instances of
*module-protocol-native-tcp* loaded, then the unload() method
of those would call `server_free()` on already freed servers,
resulting in use-after-frees. Fix that by unloading modules
before destroying the servers.
==451490==ERROR: AddressSanitizer: heap-use-after-free on address 0x612000006050 ...
READ of size 8 at 0x612000006050 thread T0
#0 0x7f45edb19a0c in server_free ../src/modules/module-protocol-pulse/server.c:1022
#1 0x7f45edb46c7d in module_native_protocol_tcp_unload ../src/modules/module-protocol-pulse/modules/module-native-protocol-tcp.c:66
#2 0x7f45eda893c7 in module_unload ../src/modules/module-protocol-pulse/module.c:128
#3 0x7f45edaf7269 in impl_unload_module ../src/modules/module-protocol-pulse/pulse-server.c:5336
#4 0x7f45edaa1583 in pw_map_for_each ../src/pipewire/map.h:238
#5 0x7f45edaf79c5 in impl_clear ../src/modules/module-protocol-pulse/pulse-server.c:5358
...
0x612000006050 is located 16 bytes inside of 264-byte region [0x612000006040,0x612000006148)
freed by thread T0 here:
#0 0x7f45f30be672 in __interceptor_free /usr/src/debug/gcc/libsanitizer/asan/asan_malloc_linux.cpp:52
#1 0x7f45edb1a48a in server_free ../src/modules/module-protocol-pulse/server.c:1040
#2 0x7f45edaf730b in impl_clear ../src/modules/module-protocol-pulse/pulse-server.c:5347
...
Fixes: f181210b29 ("pulse-server: properly unload modules")
Assume that capture and playback nodes from a device have different
clocks. This enables the adative resampler to match them. A lot of devices
actually have slightly different rates and would work out of the box
with this fix.
Make an exception when the card is configured in the pro audio profile.
Then we force the same clock on all device nodes and avoid resampling
and rate matching. This can still be changed with a session manager
override.
It causes some headsets behave strangely. See pipewire#2391,
pipewire#1853.
The BlueZ issue of AVRCP volume sometimes missing that this worked
around was fixed in recent versions. The issue of some headsets not
sending volume without AVRCP player remains, but it appears this breaks
more headsets than fixes.
Don't try to reconnect or wait for profiles, which cannot be connected
because the adapter doesn't have the counterpart sink/source profile.
E.g. we should not reconnect/wait for HFP HF on remote device, if
we don't have the corresponding HFP AG.
If A2DP remote does not acquire its pending transport within a timeout,
we won't get a write error in a2dp-sink, but instead the transport
becomes idle. Currently, we continue writing to the socket as if
everything was fine, even though the data won't be processed at the
remote end.
Handle this by stopping the node and emitting a node error event.
Pipewire may then restart the node to retry.
If the follower of the adapter emits an error event, the adapter needs
to forward it to upper levels so that they know the node has errored,
and handle the situation.
As Coverity correctly points out, the `if (blocklist)` condition
is never true after the `out` label, so this commit makes some
changes to remove the dead code.
First of all, the `regex_t` object is directly embedded in the
module's data struct, so the `malloc()` call can be removed,
and thus there is no need for the cleanup code anymore, so everything
after the `out` label is also removed.
Furthermore, two NULL checks are removed which check `d->blocklist`
from `module_switch_on_connect_unload()` and `manager_added()`
because both of those functions can only ever run if the `d->blocklist`
regex object has been successfully initialized in `module_switch_on_connect_prepare()`.
Those checks were not strictly needed to begin with.
Endpoints without decode/encode capability are skipped in the object
manager, but we should also skip them in the registration calls (even
though in practice this doesn't appear to matter).
The client needs to be cleaned up properly, otherwise references
to its storage may remain, which can later result in use-after-frees.
For example, the via the various embedded `spa_hook`s in it.
See #2394
Check pointers before calling the destructors (where needed), so that
a not fully constructed `client` object may be passed to `jack_client_close()`.
Furthermore, remove the metadata proxy and object listeners as well.
Move the initialization of some of `client`'s members right after
allocation, so that it will be simpler to tear down the client object
even if `jack_client_open()` fails later.
Furthermore, initialize `client::driver_id` to `SPA_ID_INVALID`.
It is already logged by the module loading code when a module is
successfully loaded, so there is no need to print it on a per-module
basis at the same log level.
Check all pending streams to see if the new link completes their
creation.
It is possible that the link linked 2 pending streams and then we
want to complete them both.
All modules need to manually create a `module` object and check
if it was successfully created. The same with argument parsing.
To simplify modules, move the module object creation and argument
parsing into `module_create()`, and pass the already initialized
module to `module_info::create()`.
The semantics of `module_info::create()` are kept, that is,
if it fails, `module_info::unload()` will not be called.
Now that the module's properties are served from `module_info::properties`,
there is no need for modules to put their static properties into
the `module::props` dictionary.
When filling up the channels, either fill up the positions with one
of the know layouts or use AUX channels, never try to mix them.
This avoid cards with a large number channels to show a strange mix
of surround and AUX channels.
Since gst_fd_allocator_alloc lazy mmap's the buffer to the assigned
file descriptor we can get downstream mmap failures if the pipewire
src(such as the v4l2 spa plugin) closes the file descriptor before
it gets mmap'd. To prevent the closed original file descriptor from
causing a mmap failure dup the file descriptor so that the original
being closed doesn't invalidate the descriptor passed to
gst_fd_allocator_alloc.
Add some more validation to dequeue_buffer as well.
Signed-off-by: James Hilliard <james.hilliard1@gmail.com>
Register a pthread cleanup handler to guarantee
that `spa_source::{priv, rmask}` are cleared even
if the thread is cancelled while the loop is dispatching.
This is necessary, otherwise `spa_source::priv` could point
to the stack of the cancelled thread, which will lead to
problems like this later:
Program terminated with signal SIGSEGV, Segmentation fault.
#0 0x00007f846b025be2 in detach_source (source=0x7f845f435f60) at ../spa/plugins/support/loop.c:144
144 e->data = NULL;
[Current thread is 1 (LWP 5274)]
(gdb) p e
$1 = (struct spa_poll_event *) 0x7f845e297820
(gdb) bt
#0 0x00007f846b025be2 in detach_source (source=0x7f845f435f60) at ../spa/plugins/support/loop.c:144
#1 0x00007f846b0276ad in free_source (s=0x7f845f435f60) at ../spa/plugins/support/loop.c:359
#2 0x00007f846b02a453 in loop_destroy_source (object=0x7f845f3af478, source=0x7f845f435f60) at ../spa/plugins/support/loop.c:786
#3 0x00007f846b02a886 in impl_clear (handle=0x7f845f3af478) at ../spa/plugins/support/loop.c:859
#4 0x00007f846b172f40 in unref_handle (handle=0x7f845f3af450) at ../src/pipewire/pipewire.c:211
#5 0x00007f846b173579 in pw_unload_spa_handle (handle=0x7f845f3af478) at ../src/pipewire/pipewire.c:346
#6 0x00007f846b15a761 in pw_loop_destroy (loop=0x7f845f434e30) at ../src/pipewire/loop.c:159
#7 0x00007f846b135d8e in pw_data_loop_destroy (loop=0x7f845f434cb0) at ../src/pipewire/data-loop.c:166
#8 0x00007f846b12c31c in pw_context_destroy (context=0x7f845f41c690) at ../src/pipewire/context.c:485
#9 0x00007f846b3ddf9e in jack_client_close (client=0x7f845f3c1030) at ../pipewire-jack/src/pipewire-jack.c:3481
...
Make sure to never send less than the negotiated fragsize to a client.
Also make sure we don't send too much data in one go. This is more in
line with what pulseaudio does.
Fixes capture from multiple tabs in chrome.
Fixes#2418