]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
agetty: Process all data from ul_nl_process()
authorStanislav Brabec <sbrabec@suse.cz>
Fri, 10 Oct 2025 11:17:26 +0000 (13:17 +0200)
committerStanislav Brabec <sbrabec@suse.cz>
Fri, 10 Oct 2025 12:21:16 +0000 (14:21 +0200)
However select() normally triggers immediately after a partial read, it does not
happen for netlink socket. It keeps unprocessed data until the next netlink
message appears. It causes raising processing delays.

Always read all data. It also potentially decreases number of issue redraws.

Signed-off-by: Stanislav Brabec <sbrabec@suse.cz>
include/netlink.h
term-utils/agetty.c

index 3d7c3da04f9fb3aa9c09663551d994da088ff5d0..ee4917b39c4fd007129fe8b0a9353d2b16a368bb 100644 (file)
@@ -40,7 +40,9 @@
                             * reach unprocessed NLMSG_DONE */
 #define        UL_NL_SOFT_ERROR 4  /* soft error, indicating a race condition or
                             * message relating to events before program
-                            * start); could be optionally ignored */
+                            * start); could be optionally ignored and it
+                            * should not considered as a reason to leave the
+                            * processing */
 
 struct ul_nl_data;
 
@@ -139,6 +141,8 @@ int ul_nl_request_dump(struct ul_nl_data *nl, uint16_t nlmsg_type);
 /* Process netlink messages.
  * async: If true, return UL_NL_WOULDBLOCK immediately if there is no data
  *   ready. If false, wait for a message.
+ *   NOTE: You should read all data until you get UL_NL_WOULDBLOCK, otherwise
+ *         select() will not trigger even if there is a netlink message.
  * loop: If true, run in a loop until NLMSG_DONE is received. Returns after
  *   finishing a reply from ul_nl_request_dump(), otherwise it acts as an
  *   infinite loop. If false, it returns after processing one message.
index ec922bd1119fe3b8018148499bd11d0d772b6bf6..08d009261e1f922b14b24e8c5f49c73127702506 100644 (file)
@@ -1654,9 +1654,17 @@ static int wait_for_term_input(struct issue *ie, int fd)
                }
 
                if (ie->nl.fd >= 0 && FD_ISSET(ie->nl.fd, &rfds)) {
-                       /* We are ignoring errors here to prevent unability of
-                        * further processing. */
-                       ul_nl_process(&(ie->nl), UL_NL_ASYNC, UL_NL_ONESHOT);
+                       int rc;
+
+                       /* We are looping until it returns UL_NL_WOULDBLOCK.
+                        * To prevent infinite loop, we are leaving on any other
+                        * error except UL_NL_SOFT_ERROR. To prevent unability
+                        * of further processing, we never exit. */
+                       do {
+                               rc = ul_nl_process(&(ie->nl), UL_NL_ASYNC,
+                                                  UL_NL_ONESHOT);
+                       }
+                       while (!rc || rc == UL_NL_SOFT_ERROR);
 
                /* Just drain the inotify buffer */
                } else if (inotify_fd >= 0 && FD_ISSET(inotify_fd, &rfds)) {