Skip to content

kernelize one stream at a time, and keep a stream with too many outputs in userspace - #2241

Open
nickakt wants to merge 1 commit into
sipwise:masterfrom
nickakt:fix/kernelize-livelock
Open

nickakt wants to merge 1 commit into
sipwise:masterfrom
nickakt:fix/kernelize-livelock

Conversation

@nickakt

@nickakt nickakt commented Nov 10, 2026

Copy link
Copy Markdown

kernelize_one() takes each sink's lock with a trylock, and kernelize() starts over at once when one is busy. Streams that are each other's sinks hold their own lock while they try the other's, so they start over against each other. After a change of subscriptions all of them are kernelized on their next packet, at the same moment. With about eight or more such streams the restarts do not end: the threads spin with the call's master lock held, the streams' sockets are no longer read, the log fills with "Kernelizing media stream" lines, and commands for the call are not answered. A static lock around kernelize() leaves the trylock only holders outside of it; the call iterators take their list lock ahead of their trylocks in the same way.

A stream with more than RTPE_MAX_FORWARD_DESTINATIONS outputs, two per sink, was pushed to the kernel anyway: the module answered EINVAL, each output ENOENT, and the stream was still marked kernelized. It now takes the no_kernel path.

The limit itself is left as it is. It came with 01a10c0, where it sized the array of outputs in struct rtpengine_list_entry; that struct is gone, and until now the module's check was its only use.

kernelize_one() takes each sink's lock with a trylock, and kernelize() starts
over at once when one is busy. Streams that are each other's sinks hold their
own lock while they try the other's, so they start over against each other.
After a change of subscriptions all of them are kernelized on their next
packet, at the same moment. With about eight or more such streams the
restarts do not end: the threads spin with the call's master lock held, the
streams' sockets are no longer read, the log fills with "Kernelizing media
stream" lines, and commands for the call are not answered. A static lock
around kernelize() leaves the trylock only holders outside of it; the call
iterators take their list lock ahead of their trylocks in the same way.

A stream with more than RTPE_MAX_FORWARD_DESTINATIONS outputs, two per sink,
was pushed to the kernel anyway: the module answered EINVAL, each output
ENOENT, and the stream was still marked kernelized. It now takes the
no_kernel path.

The limit itself is left as it is. It came with 01a10c0, where it sized
the array of outputs in struct rtpengine_list_entry; that struct is gone, and
until now the module's check was its only use.
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

Successfully merging this pull request may close these issues.

1 participant