nettester So there either has to be some kind of code that ignores return codes turning something that should really wait for data into an eternal spinlock or said return codes are bogus (like select instantly returning without failure but no events despite timeout) and thus tricking mutt into thinking everything is fine.
Another scenario is the system-time going backwards across a suspend, and mutt
not expecting that to happen.
For example, see the raw_socket_poll()
function in mutt_socket.c
. It uses gettimeofday()
pairs to (portably) determine if select()
returned with a "short" sleep, and then compensate for that. The way it does this is fine in most cases--except if the second gettimeofday()
returns a time before that of the first gettimeofday()
. Then the code will sleep for much longer than anticipated.
gettimeofday()
should not be used for monotonic time intervals. If you want a monotonic interval, the system generally provides a better one.
@szilard Please try this patch:
diff -urN mutt-2.2.10.orig/mutt_socket.c mutt-2.2.10/mutt_socket.c
--- mutt-2.2.10.orig/mutt_socket.c 2023-03-25 19:50:20.000000000 +0000
+++ mutt-2.2.10/mutt_socket.c 2023-07-21 14:10:02.712062000 +0000
@@ -517,7 +517,8 @@
{
fd_set rfds;
unsigned long long wait_millis, post_t_millis;
- struct timeval tv, pre_t, post_t;
+ struct timeval tv;
+ struct timespec pre_t, post_t;
int rv;
if (conn->fd < 0)
@@ -533,9 +534,9 @@
FD_ZERO (&rfds);
FD_SET (conn->fd, &rfds);
- gettimeofday (&pre_t, NULL);
+ clock_gettime (CLOCK_MONOTONIC, &pre_t);
rv = select (conn->fd + 1, &rfds, NULL, NULL, &tv);
- gettimeofday (&post_t, NULL);
+ clock_gettime (CLOCK_MONOTONIC, &post_t);
if (rv > 0 ||
(rv < 0 && errno != EINTR))
@@ -545,9 +546,9 @@
mutt_query_exit ();
wait_millis += ((unsigned long long)pre_t.tv_sec * 1000ULL) +
- (unsigned long long)(pre_t.tv_usec / 1000);
+ (unsigned long long)(pre_t.tv_nsec / (1000 * 1000));
post_t_millis = ((unsigned long long)post_t.tv_sec * 1000ULL) +
- (unsigned long long)(post_t.tv_usec / 1000);
+ (unsigned long long)(post_t.tv_nsec / (1000 * 1000));
if (wait_millis <= post_t_millis)
return 0;
wait_millis -= post_t_millis;
EDIT: Upon reflection, this scenario would only result in unwanted sleeps, not the high CPU-loading you observed. So, compile mutt
for debugging and run it in the debugger. We should be able to see what's spinning.