server: Fix race condition in com_stat().
authorAndre Noll <maan@tuebingen.mpg.de>
Wed, 9 Nov 2022 19:46:48 +0000 (20:46 +0100)
committerAndre Noll <maan@tuebingen.mpg.de>
Fri, 25 Nov 2022 12:22:16 +0000 (13:22 +0100)
We need to block not only SIGTERM but also SIGUSR1 in the command
handler of the stat server command because otherwise the signal is
lost if it arrives within a small race window. If this happens, the
next status update will be up to 50 seconds late. The race condition
is even explained in the comment nearby...

The bug was observed in a situation where the last admissible file
of the current mood became inadmissible, causing the server to stop
streaming. This is reflected by the status flags transition from P
(playing) to N (stopped) via the intermediate state PN (trying to
load next file). After either transition the server process sends
SIGUSR1 to the command handler.

If the second signal arrives just after the PN state was sampled
but before the command handler goes to sleep by calling pselect(2),
the signal handler runs and sets subcmd_should_die, but this won't be
acted upon until after we sleep for up to 50 seconds in pselect(2). As
a result, para_audiod, hence para_gui, keep reporting the stale PN
state during this period.

This bug was present in the code base since day one of the git repo
in 2006.

command.c

index 0c483befe3adfd8899756c99feed7c30b003850d..427c90fe13fe6ccc0f6fd5259c24f45e69f211fa 100644 (file)
--- a/command.c
+++ b/command.c
@@ -514,6 +514,7 @@ static int com_stat(struct command_context *cc, struct lls_parse_result *lpr)
         * while we sleep.
         */
        para_block_signal(SIGTERM);
+       para_block_signal(SIGUSR1);
        for (;;) {
                sigset_t set;
                /*