gui: Don't sleep before executing the status command.
authorAndre Noll <maan@systemlinux.org>
Wed, 27 Mar 2013 20:49:40 +0000 (20:49 +0000)
committerAndre Noll <maan@systemlinux.org>
Thu, 2 May 2013 17:56:09 +0000 (19:56 +0200)
This results in uncacceptable delays when the status command fails
for any reason, for example because the server is down.

Replace this code by introducing a struct timeval variable "next_exec",
which stores the earliest possible time to restart the status command.

Move all status fetching code before the select() call in do_select()
to open_stat_pipe() and rename the function to status_pre_select(),
which is more appropriate.

configure.ac
gui.c

index 4512c6f..35c9fd5 100644 (file)
@@ -153,7 +153,7 @@ client_errlist_objs="client net string fd sched stdin stdout time sideband
 client_ldflags=""
 
 gui_cmdline_objs="add_cmdline(gui)"
-gui_errlist_objs="exec signal string stat ringbuffer fd gui gui_theme"
+gui_errlist_objs="exec signal string stat ringbuffer fd gui gui_theme time"
 gui_objs="$gui_cmdline_objs $gui_errlist_objs"
 play_errlist_objs="play fd sched ggo buffer_tree time string net
        afh_recv afh_common
diff --git a/gui.c b/gui.c
index 6e44b09..fb70dd8 100644 (file)
--- a/gui.c
+++ b/gui.c
@@ -10,6 +10,7 @@
 #include <signal.h>
 #include <sys/types.h>
 #include <curses.h>
+#include <sys/time.h>
 
 #include "gui.cmdline.h"
 #include "para.h"
@@ -930,30 +931,33 @@ static void handle_signal(int sig)
        }
 }
 
-static int open_stat_pipe(void)
+static void status_pre_select(fd_set *rfds, int *max_fileno, struct timeval *tv)
 {
-       static int init = 1;
+       static struct timeval next_exec, atm, diff;
        int ret, fds[3] = {0, 1, 0};
        pid_t pid;
 
-       if (init)
-               init = 0;
-       else
-               /*
-                * Sleep a bit to avoid a busy loop. As the call to sleep() may
-                * be interrupted by SIGCHLD, we simply wait until the call
-                * succeeds.
-                */
-               while (sleep(2))
-                       ; /* nothing */
+       if (stat_pipe >= 0)
+               goto success;
+       /* Avoid busy loop */
+       gettimeofday(&atm, NULL);
+       if (tv_diff(&next_exec, &atm, &diff) > 0) {
+               if (tv_diff(&diff, tv, NULL) < 0)
+                       *tv = diff;
+               return;
+       }
+       next_exec.tv_sec = atm.tv_sec + 2;
        ret = para_exec_cmdline_pid(&pid, conf.stat_cmd_arg, fds);
        if (ret < 0)
-               return ret;
+               return;
        ret = mark_fd_nonblocking(fds[1]);
-       if (ret >= 0)
-               return fds[1];
-       close(fds[1]);
-       return ret;
+       if (ret < 0) {
+               close(fds[1]);
+               return;
+       }
+       stat_pipe = fds[1];
+success:
+       para_fd_set(stat_pipe, rfds, max_fileno);
 }
 
 #define COMMAND_BUF_SIZE 32768
@@ -985,10 +989,7 @@ repeat:
 //     ret = refresh_status();
        FD_ZERO(&rfds);
        max_fileno = 0;
-       if (stat_pipe < 0)
-               stat_pipe = open_stat_pipe();
-       if (stat_pipe >= 0)
-               para_fd_set(stat_pipe, &rfds, &max_fileno);
+       status_pre_select(&rfds, &max_fileno, &tv);
        /* signal pipe */
        para_fd_set(signal_pipe, &rfds, &max_fileno);
        /* command pipe only for COMMAND_MODE */