# Getting Pulseaudio to schedule real-time threads under Debian / Stretch and beyond.

On the computer which I name ‘Phosphene’, I have Debian 9 / Stretch installed, and, going the popular route, the Debian maintainers have decided that ‘Pulseaudio’ should be the main sound server, while in certain cases, it can be made to coexist with the ‘Jack’ / ‘Jack v2′ daemon, the latter for more demanding needs. In my case, starting Jack suspends Pulse.

In addition, Debian systems I’m familiar with run ‘pulseaudio’ as user, and not as root.

But, the way my Pulse daemon is configured, includes a ‘loopback’ module, that sends audio that has been input and sampled from the analog input of my (“Creative X-Fi”) sound card, back to its analog output, so that I can listen to an old-fashioned-but-modern radio receiver, over my speakers, without having to connect anything special to do so.

The problem that I was experiencing was, buffer underruns, and sound drop-outs, due to the way this default sound server was operating the sound card. And, surely enough, it had something to do with a by-now famous issue, of allowing Pulse to schedule certain threads to run with real-time priority. This can be enabled in the config file ‘/etc/pulse/daemon.conf‘, but fails to become actual when just enabled so.

Trying to find an answer to why this attempt was failing, sent me on a trip to many Web-sites and BB-postings, most of which had as disadvantage, the fact that with Pulse, there is an old way and a new way to accomplish this, and the fact that most of the BB-postings assumed the old way, being dated to the year 2016 and earlier.

Rest assured, under Debian 9 / Stretch, authorizing Pulse to schedule some threads with RT priority, is managed according to ‘the new way’. Just to recap how ‘the old way’ worked:

The file ‘/usr/bin/pulseaudio‘ needed to be set with ‘SETUID root’, and when run this way, if the sound server detected that the real user (not the effective user) belonged to the group ‘pulse-rt‘, would schedule the threads it needed to run with RT, and would then drop privileges, so that according to the process-monitor ‘top’, it would never even give a hint that anything had in fact been scheduled with RT.

This is how ‘the new way’ is supposed to work:

If the user needs for Pulse specifically to run with RT, he must actually install the package ‘rtkit‘, which runs as a system user, and which sets certain threads to have RT priority in a curated way, that’s meant to be ‘safer’, than it still is for any one user to belong to a group, that simply allows him or her to run arbitrary processes with RT. In fact, ‘the old way’ was also meant as a similar safeguard.

I had installed the specified package, rebooted my system – with Pulse given its new startup parameters, and found alas, that the file ‘/var/log/syslog‘, which was benefiting from an elevated logging level set by me, revealed numerous messages that I did not understand.

Trying to figure out what was happening resulted in more than one day’s frustration, and then finally, to some peace of mind…

(Updated 4/16/2020, 13h15 … )

Because I have now configured my system to my liking, Pulse is able to obtain RT, but does not use this, except for 2 threads in total, that control the sound card, but that do not include my ‘loopback’ module. Therefore, the loopback module could still suffer from occasional buffer underruns, that are not the result of any failings of RT threads, but that result from the failings of the regular priority with which the Pulse daemon runs.

For that last reason, I next decided to create a group named ‘pulse-rt‘, because none is installed anymore by the Debian maintainers. Then, I also configured the ability of Pulse to run with ‘lock-memory = yes‘, ‘realtime-scheduling = yes‘, ‘realtime-priority = 5‘, ‘high-priority = yes‘, and with ‘nice-level = -20‘. The following is what the end of my system-wide configuration file ‘/etc/security/limits.conf‘ looked like:


@users          soft    nproc           1024
@pulse-rt       -       memlock         unlimited

root            -       rtprio          95

# End of file




Also, I added myself to the group ‘pulse-rt‘, and gave the command ‘chmod u+s /usr/bin/pulseaudio‘ as root. Then, because I had changed the permissions of ‘root‘ above, I needed to reboot.

Actually allowing the daemon to run with ‘SETUID root’, gives it the permissions it needs to ‘renice’ itself.

And the way it happens now is that, due to whatever weaknesses still exist, in how the ‘loopback’ module is being scheduled (and, preempted in some cases), buffer-underruns will take place in the thread that controls my audio sink, once every few hours. This is because the loopback module fell behind in generating output for that sink, but a stream was configured for it. Each time this happens, Pulse increases the configured latency, which has now stopped at “26000 microseconds”. Did I mention, I also added the parameter ‘tsched_buffer_size=32768‘ to the module ‘module-udev-detect‘, which was already being loaded by the file ‘/etc/pulse/default.pa‘?

And, with some degree of relief, I am now able to listen to my FM radio, without any stuttering, and more-or-less as well as Pulse can deliver the sound.


top - 13:08:02 up 2 days, 57 min,  2 users,  load average: 0.10, 0.17, 0.17
Tasks: 306 total,   1 running, 305 sleeping,   0 stopped,   0 zombie
%Cpu(s):  1.3 us,  1.1 sy,  0.0 ni, 97.2 id,  0.3 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem : 12297756 total,  2087432 free,  3080716 used,  7129608 buff/cache
KiB Swap: 34680828 total, 34680828 free,        0 used.  8356156 avail Mem

PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND
4576 dirk       5 -15 1261592 882696 861912 S   5.0  7.2   0:49.84 pulseaudio
1467 root      20   0  308136  87128  47676 S   3.0  0.7  71:12.29 Xorg
2617 dirk      20   0  257732  22328  18792 S   2.3  0.2  73:49.98 gkrellm
2517 dirk      20   0 3182248 127644  83096 S   1.7  1.0  67:46.76 kwin_x11
1497 root      20   0  977604   9324   8136 S   1.3  0.1  14:04.78 collectd
2563 dirk      20   0 5205240 746268 207088 S   0.7  6.1   7:30.20 plasmashell
3312 dirk      20   0 3073832 228264  99540 S   0.7  1.9  19:26.89 calibre
5196 dirk      20   0   45060   3948   3104 R   0.7  0.0   0:00.08 top
1006 root      20   0       0      0      0 S   0.3  0.0   0:08.55 jbd2/sda2-8
2042 root      20   0       0      0      0 S   0.3  0.0   0:01.66 kworker/0:1
2561 dirk      20   0  639096  48168  38432 S   0.3  0.4   0:37.33 kdeconnectd
2698 dirk      20   0  633348  57484  27316 S   0.3  0.5   3:47.65 overgrive
2805 dirk      20   0  625016  31224  12516 S   0.3  0.3   4:31.11 syncthing
3983 dirk      20   0 5358984 272264  75288 S   0.3  2.2   3:25.47 dropbox
5026 dirk      20   0 1484492  76524  58872 S   0.3  0.6   0:01.62 konsole
29140 root      20   0       0      0      0 S   0.3  0.0   0:05.03 kworker/1:0
1 root      20   0  205104   7420   5240 S   0.0  0.1   0:06.26 systemd
2 root      20   0       0      0      0 S   0.0  0.0   0:00.08 kthreadd
3 root      20   0       0      0      0 S   0.0  0.0   0:05.23 ksoftirqd/0
5 root       0 -20       0      0      0 S   0.0  0.0   0:00.00 kworker/0:+
7 root      20   0       0      0      0 S   0.0  0.0   2:15.54 rcu_sched
8 root      20   0       0      0      0 S   0.0  0.0   0:00.00 rcu_bh
9 root      rt   0       0      0      0 S   0.0  0.0   0:00.39 migration/0
10 root       0 -20       0      0      0 S   0.0  0.0   0:00.00 lru-add-dr+
11 root      rt   0       0      0      0 S   0.0  0.0   0:00.39 watchdog/0
12 root      20   0       0      0      0 S   0.0  0.0   0:00.00 cpuhp/0
13 root      20   0       0      0      0 S   0.0  0.0   0:00.00 cpuhp/1
14 root      rt   0       0      0      0 S   0.0  0.0   0:00.33 watchdog/1
15 root      rt   0       0      0      0 S   0.0  0.0   0:00.38 migration/1
16 root      20   0       0      0      0 S   0.0  0.0   0:02.26 ksoftirqd/1
18 root       0 -20       0      0      0 S   0.0  0.0   0:00.00 kworker/1:+
19 root      20   0       0      0      0 S   0.0  0.0   0:00.00 cpuhp/2
20 root      rt   0       0      0      0 S   0.0  0.0   0:00.31 watchdog/2

dirk@Phosphene:~$pactl list short sources 0 alsa_output.pci-0000_07_00.0.analog-stereo.monitor module-alsa-card.c s16le 2ch 96000Hz IDLE 1 alsa_input.pci-0000_07_00.0.analog-stereo module-alsa-card.c s16le 2ch 96000Hz RUNNING dirk@Phosphene:~$ pactl list short sinks
0       alsa_output.pci-0000_07_00.0.analog-stereo      module-alsa-card.c     s16le 2ch 96000Hz        RUNNING
dirk@Phosphene:~$pactl list sources | grep Latency Latency: 0 usec, configured 85333 usec Latency: 19 usec, configured 6666 usec dirk@Phosphene:~$ pactl list sinks | grep Latency
Latency: 5477 usec, configured 6666 usec
dirk@Phosphene:~\$




Dirk

## One thought on “Getting Pulseaudio to schedule real-time threads under Debian / Stretch and beyond.”

1. Martinliaxy says:

It is very nice to read your site, thank you very much for your work, it’s great!