Skip to content

linux-user: fails to deliver signals raised during pselect

Host environment

  • Operating system: NixOS
  • OS/kernel version: Linux nix-build 5.10.92 #1-NixOS SMP Sun Jan 16 08:14:24 UTC 2022 x86_64 GNU/Linux
  • Architecture: x86_64
  • QEMU flavor: linux-user
  • QEMU version: qemu-x86_64 version 6.2.50 (v6.2.0-1117-gaeb0ae95)

Description of problem

When run via qemu a program which blocks signals but unmasks them during pselect does not catch these signals when returning from pselect.

Used as reference on expected behavior: The new pselect() system call

Steps to reproduce

A minimal test case below mimics behavior as encountered in the test suite of p11-kit (link) (which attempts to catch SIGTERM in a similar way and results in lingering processes after running the test suite).

#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <sys/select.h>

static void handler(int sig)
{
	puts("SIGNAL");
}

int main(int argc, char *argv[])
{
	struct sigaction sa;

	fd_set rfds;
	sigset_t emptyset, blockset;

	sigemptyset (&blockset);
	sigemptyset (&emptyset);
	sigaddset (&blockset, SIGUSR1);

	sa.sa_handler = handler;
	sigemptyset(&sa.sa_mask);
	sa.sa_flags = 0;
	sigaction(SIGUSR1, &sa, NULL);

	sigprocmask (SIG_BLOCK, &blockset, NULL);

	FD_ZERO(&rfds);

	while(1) {
		pselect(0, &rfds, NULL, NULL, NULL, &emptyset);
	}

	return 0;
}

Running this without qemu should print SIGNAL when sent SIGUSR1:

$ ./a.out &
[1] 1683587
$ kill -USR1 %1
$ SIGNAL

When run with qemu-x86_64 however, it does not (also qemu's -strace confirms the signal isn't received whereas a strace of qemu shows it's in fact delivered).

The pselect call itself is interrupted, but the signal goes missing.

To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information