[Cluster-devel] [PATCH v2] glocktop: Fix a tight loop under nohup
Andreas Gruenbacher
agruenba at redhat.com
Tue Mar 1 21:35:10 UTC 2016
On Tue, Mar 1, 2016 at 8:43 PM, Andrew Price <anprice at redhat.com> wrote:
> When glocktop is run under nohup, /dev/null is redirected to stdin,
> which flags up EOF and causes the file descriptor to always be in a
> ready state when select()ed. This causes select() to return immediately
> instead of timing out after the refresh delay.
>
> Remove stdin from the fd_set when we get EOF to avoid getting into a
> tight loop when run under nohup.
>
> Also fix up some messages relating to the refresh interval.
>
> Signed-off-by: Andrew Price <anprice at redhat.com>
> ---
> gfs2/glocktop/glocktop.c | 24 +++++++++++++++++-------
> 1 file changed, 17 insertions(+), 7 deletions(-)
>
> diff --git a/gfs2/glocktop/glocktop.c b/gfs2/glocktop/glocktop.c
> index 43c3c3f..01b8099 100644
> --- a/gfs2/glocktop/glocktop.c
> +++ b/gfs2/glocktop/glocktop.c
> @@ -147,7 +147,6 @@ enum summary_types {
> char debugfs[PATH_MAX];
> int termcols = 80, termlines = 30, done = 0;
> unsigned glocks = 0;
> -int refresh_time = REFRESH_TIME;
> const char *termtype;
> WINDOW *wind;
> int bufsize = 4 * 1024 * 1024;
> @@ -1625,7 +1624,7 @@ static void usage(void)
> "[-c] [-D] [-H] [-r] [-t]\n");
> printf("\n");
> printf("-i : Runs glocktop in interactive mode.\n");
> - printf("-d : delay between refreshes, in seconds (default: 3).\n");
> + printf("-d : delay between refreshes, in seconds (default: %d).\n", REFRESH_TIME);
> printf("-n : stop after <iter> refreshes.\n");
> printf("-H : don't show Held glocks, even if not waited on, excluding "
> "iopen\n");
> @@ -1645,7 +1644,7 @@ int main(int argc, char **argv)
> char fn[PATH_MAX];
> struct dirent *dent;
> int retval;
> - struct timeval tv;
> + int refresh_time = REFRESH_TIME;
> fd_set readfds;
> char string[96];
> int ch, i, dlmwaiters = 0, dlmgrants = 0;
> @@ -1654,6 +1653,7 @@ int main(int argc, char **argv)
> int show_held = 1, help = 0;
> int interactive = 0;
> int summary = 10;
> + int nfds;
>
> prog_name = argv[0];
> memset(glock, 0, sizeof(glock));
> @@ -1669,7 +1669,7 @@ int main(int argc, char **argv)
> refresh_time = atoi(optarg);
> if (refresh_time < 1) {
> fprintf(stderr, "Error: delay %d too small; "
> - "must be > 1\n", refresh_time);
> + "must be at least 1\n", refresh_time);
> exit(-1);
> }
> break;
> @@ -1758,7 +1758,13 @@ int main(int argc, char **argv)
> bufsize /= 2;
> }
>
> + FD_ZERO(&readfds);
> + FD_SET(STDIN_FILENO, &readfds);
> + nfds = STDIN_FILENO + 1;
> +
> while (!done) {
> + struct timeval tv;
> +
> sprintf(fn, "%s/gfs2/", debugfs);
> dir = opendir(fn);
>
> @@ -1828,9 +1834,7 @@ int main(int argc, char **argv)
> closedir(dir);
> tv.tv_sec = refresh_time;
> tv.tv_usec = 0;
> - FD_ZERO(&readfds);
> - FD_SET(0, &readfds);
> - retval = select(1, &readfds, NULL, NULL, &tv);
> + retval = select(nfds, &readfds, NULL, NULL, &tv);
No, the readfds set must be initialized in the loop, before each call
to select. It is modified in-place.
> if (retval) {
> if (interactive)
> ch = getch();
> @@ -1856,6 +1860,12 @@ int main(int argc, char **argv)
> if (refresh_time < 1)
> refresh_time = 1;
> break;
> + /* When we get EOF on stdin, remove it from the fd_set
> + to avoid shorting out the select() */
> + case EOF:
> + FD_CLR(STDIN_FILENO, &readfds);
> + nfds = 0;
> + break;
> }
> }
> iters_done++;
> --
> 2.4.3
>
Thanks,
Andreas
More information about the Cluster-devel
mailing list