Polling /dev/kmsg on older linuxes makes the kernel very excited to tell
you that it has something for you to read()!
Unfortunately, that's EINVAL.[1]
Ignoring these errors only makes the kernel even more excited, so let's
close /dev/kmsg immediately after getting EINVAL to get out of
a constant error loop and let the cpu calm down.
This change improves system performance on old devices that don't have
mainlined kernel.
Similar behaviour can be seen in journald:
https://github.com/systemd/systemd/blob/a7d8cacce0cb0451701b81db818d9e5921574f51/src/journal/journald-kmsg.c#L320-L326
[1]: Reading from /dev/kmsg was introduced in Linux 3.5:
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=e11fea92e13fb91c50bacca799a6131c81929986
---
main.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/main.c b/main.c
index c848944..f5f8788 100644
--- a/main.c+++ b/main.c
@@ -1055,7 +1055,13 @@ main(int argc, char *argv[])
if (kmsg_fd > 0 && FD_ISSET(kmsg_fd, &read_fd_set)) {
ssize_t size;
size = read(kmsg_fd, recvbuf, MAX_MESSAGE_SIZE - 1);
- parse_kmsg_line(recvbuf, size);+ if (size < 0 && errno == EINVAL) {+ self_log(SEV_NOTICE, "Reading from /dev/kmsg returned EINVAL, you are probably using linux<3.5. Continuing without kernel messages support");+ close(kmsg_fd);+ kmsg_fd = 0;+ } else {+ parse_kmsg_line(recvbuf, size);+ } }
if (FD_ISSET(logread_fd, &read_fd_set)) {
int new_client_fd = accept(logread_fd, NULL, NULL);
--
2.44.0