[LTP] [PATCH 2/2] poll: add test for POLLNVAL on invalid fd

Cyril Hrubis chrubis@suse.cz
Fri Feb 20 11:05:06 CET 2026


Hi!
> Add a poll() test to verify that POLLNVAL is reported for invalid file
> descriptors.
> 
> The test closes one end of a pipe and passes the closed descriptor to
> poll(). poll() is expected to return successfully and set POLLNVAL in
> revents.
> 
> This verifies poll() handling of invalid file descriptors without
> triggering an error return.
> 
> Signed-off-by: Jinseok Kim <always.starving0@gmail.com>
> ---
>  testcases/kernel/syscalls/poll/poll04.c | 60 +++++++++++++++++++++++++
>  1 file changed, 60 insertions(+)
>  create mode 100644 testcases/kernel/syscalls/poll/poll04.c
> 
> diff --git a/testcases/kernel/syscalls/poll/poll04.c b/testcases/kernel/syscalls/poll/poll04.c
> new file mode 100644
> index 000000000..2013de642
> --- /dev/null
> +++ b/testcases/kernel/syscalls/poll/poll04.c
> @@ -0,0 +1,60 @@
> +// SPDX-License-Identifier: GPL-2.0-or-later
> +/*
> + * Copyright (C) 2026 Jinseok Kim <always.starving0@gmail.com>
> + */
> +
> +/*

Here as well /*\

> + * Check that poll() reports POLLNVAL for invalid file descriptors.
> + */
> +#include <unistd.h>
> +#include <errno.h>
> +#include <sys/poll.h>
> +
> +#include "tst_test.h"
> +
> +static int fds[2];
> +
> +void verify_pollnval(void)
> +{
> +	int invalid_fd = fds[0];
> +	struct pollfd pfd = {
> +		.fd = invalid_fd, .events = POLLIN,
> +	};
> +
> +	SAFE_CLOSE(fds[0]);
> +	fds[0] = -1;

Here as well, fds[0] is already set in the SAFE_CLOSE() macro.

Ah, and also this code will fail the test if we run it with -i 2 command
line parameter.

I guess that we need to do in test setup()

- copy the value of fds[0] to different variable
- close the fds[0]


Moreover it may make sense to write the test so that the fd is closed
while one thread is sleeping in the poll().

For that we would need to start a second thread that would wait for the
verify_pollnval() to sleep in the kernel and then close the fd. We do
have functions for that in the test library:

https://linux-test-project.readthedocs.io/en/latest/developers/api_c_tests.html#macro-tst-thread-state-wait


> +	TEST(poll(&pfd, 1, 0));
> +
> +	if (TST_RET == -1) {
> +		tst_res(TFAIL | TTERRNO, "poll() failed");
> +		return;
> +	}

Here as well, we should check that the return value was correct.

> +	if (!(pfd.revents & POLLNVAL)) {
> +		tst_res(TFAIL, "poll() did not report POLLNVAL");
> +		return;
> +	}

Here as well, we should check that only the flag we expected was set.

> +	tst_res(TPASS, "poll() reported POLLNVAL");
> +}
> +
> +static void setup(void)
> +{
> +	SAFE_PIPE(fds);
> +}
> +
> +static void cleanup(void)
> +{
> +	if (fds[0] >= 0)
> +		SAFE_CLOSE(fds[0]);
> +
> +	if (fds[1] >= 0)
> +		SAFE_CLOSE(fds[1]);

Here as well, either initialize fds or change the checks to >.

> +}
> +
> +static struct tst_test test = {
> +	.setup = setup,
> +	.cleanup = cleanup,
> +	.test_all = verify_pollnval,
> +};
> \ No newline at end of file
> --
> 2.43.0
> 
> -- 
> Mailing list info: https://lists.linux.it/listinfo/ltp

-- 
Cyril Hrubis
chrubis@suse.cz


More information about the ltp mailing list