From 2033c6085fd11f271059ea29a63f8a3e45f47b82 Mon Sep 17 00:00:00 2001 From: Andrew Wood Date: Sat, 23 Sep 2023 21:53:31 +0100 Subject: [PATCH] Addressed more issues raised by splint. --- configure.ac | 1 + src/include/config.h.in | 3 +++ src/include/pv-internal.h | 2 +- src/include/pv.h | 3 +++ src/main/main.c | 4 ++-- src/pv/elapsedtime.c | 27 +++++++++++++++++++++++++++ src/pv/loop.c | 30 ++++++++++++++++-------------- src/pv/watchpid.c | 10 +++++----- 8 files changed, 58 insertions(+), 22 deletions(-) diff --git a/configure.ac b/configure.ac index 0b7c687..cdfa073 100644 --- a/configure.ac +++ b/configure.ac @@ -28,6 +28,7 @@ AC_CHECK_FUNCS([getopt_long]) AC_CHECK_FUNCS([vsnprintf strlcat strtoul]) AC_CHECK_FUNCS([fdatasync]) AC_CHECK_FUNCS([fpathconf sysconf posix_memalign posix_fadvise]) +AC_CHECK_FUNCS([nanosleep]) AC_CHECK_HEADERS([getopt.h]) AC_CHECK_HEADERS([limits.h]) AC_CHECK_HEADERS([wctype.h]) diff --git a/src/include/config.h.in b/src/include/config.h.in index 26fd83a..d4a4ee6 100644 --- a/src/include/config.h.in +++ b/src/include/config.h.in @@ -88,6 +88,9 @@ /* Define to 1 if you have the `msgget' function. */ #undef HAVE_MSGGET +/* Define to 1 if you have the `nanosleep' function. */ +#undef HAVE_NANOSLEEP + /* Define to 1 if you have the `posix_fadvise' function. */ #undef HAVE_POSIX_FADVISE diff --git a/src/include/pv-internal.h b/src/include/pv-internal.h index 32e8b33..fd70e44c 100644 --- a/src/include/pv-internal.h +++ b/src/include/pv-internal.h @@ -307,7 +307,7 @@ void pv_remote_check(pvstate_t); void pv_remote_fini(pvstate_t); int pv_remote_set(pvstate_t); -int pv_watchfd_info(pvstate_t, pvwatchfd_t, int); +int pv_watchfd_info(pvstate_t, pvwatchfd_t, bool); int pv_watchfd_changed(pvwatchfd_t); off_t pv_watchfd_position(pvwatchfd_t); int pv_watchpid_scanfds(pvstate_t, pvstate_t, unsigned int, int *, pvwatchfd_t *, pvstate_t *, int *); diff --git a/src/include/pv.h b/src/include/pv.h index 24e3de1..886607c 100644 --- a/src/include/pv.h +++ b/src/include/pv.h @@ -123,6 +123,9 @@ void pv_elapsedtime_subtract(struct timespec *, const struct timespec *, const s /* Convert a timespec to seconds. */ long double pv_elapsedtime_seconds(const struct timespec *); +/* Sleep for a number of nanoseconds. */ +void pv_nanosleep(long long); + /* * Main PV functions. diff --git a/src/main/main.c b/src/main/main.c index f80b415..f26bd12 100644 --- a/src/main/main.c +++ b/src/main/main.c @@ -310,10 +310,10 @@ int main(int argc, char **argv) pv_remote_init(); retcode = pv_main_loop(state); pv_remote_fini(); - } else if (0 != opts->watch_pid && 0 == opts->watch_fd) { + } else if (0 != opts->watch_pid && -1 == opts->watch_fd) { /* "Watch all file descriptors of another process" mode. */ retcode = pv_watchpid_loop(state); - } else if (0 != opts->watch_pid && 0 != opts->watch_fd) { + } else if (0 != opts->watch_pid && -1 != opts->watch_fd) { /* "Watch a specific file descriptor of another process" mode. */ retcode = pv_watchfd_loop(state); } diff --git a/src/pv/elapsedtime.c b/src/pv/elapsedtime.c index ba427a1..64c9306 100644 --- a/src/pv/elapsedtime.c +++ b/src/pv/elapsedtime.c @@ -221,4 +221,31 @@ long double pv_elapsedtime_seconds(const struct timespec *elapsed_time) return seconds; } + +/* + * Sleep for a number of nanoseconds. + */ +void pv_nanosleep(long long nanoseconds) +{ +#if HAVE_NANOSLEEP + struct timespec sleep_for, time_remaining; + + memset(&sleep_for, 0, sizeof(sleep_for)); + memset(&time_remaining, 0, sizeof(time_remaining)); + + sleep_for.tv_sec = 0; + sleep_for.tv_nsec = nanoseconds; + (void) nanosleep(&sleep_for, &time_remaining); +#else + struct timeval tv; + tv.tv_sec = 0; + /*@-type@*/ + tv.tv_usec = nanoseconds / 1000; + /*@+type@*/ /* splint rationale - best effort */ + /*@-null@*/ + (void) select(0, NULL, NULL, NULL, &tv); + /*@+null@*/ /* splint doesn't know about select() */ +#endif +} + /* EOF */ diff --git a/src/pv/loop.c b/src/pv/loop.c index 7ded148..e6cb8a6 100644 --- a/src/pv/loop.c +++ b/src/pv/loop.c @@ -123,7 +123,9 @@ int pv_main_loop(pvstate_t state) /* * Set or clear O_DIRECT on the output. */ - fcntl(STDOUT_FILENO, F_SETFL, (state->direct_io ? O_DIRECT : 0) | fcntl(STDOUT_FILENO, F_GETFL)); + if (0 != fcntl(STDOUT_FILENO, F_SETFL, (state->direct_io ? O_DIRECT : 0) | fcntl(STDOUT_FILENO, F_GETFL))) { + debug("%s: %s", "fcntl", strerror(errno)); + } state->direct_io_changed = false; #endif /* O_DIRECT */ @@ -349,7 +351,7 @@ int pv_main_loop(pvstate_t state) state->exit_status |= 32; if (fd >= 0) - close(fd); + (void) close(fd); return state->exit_status; } @@ -375,7 +377,7 @@ int pv_watchfd_loop(pvstate_t state) memset(&info, 0, sizeof(info)); info.watch_pid = state->watch_pid; info.watch_fd = state->watch_fd; - rc = pv_watchfd_info(state, &info, 0); + rc = pv_watchfd_info(state, &info, false); if (0 != rc) { state->exit_status |= 2; return state->exit_status; @@ -401,6 +403,8 @@ int pv_watchfd_loop(pvstate_t state) memset(&cur_time, 0, sizeof(cur_time)); memset(&next_remotecheck, 0, sizeof(next_remotecheck)); memset(&next_update, 0, sizeof(next_update)); + memset(&init_time, 0, sizeof(init_time)); + memset(&transfer_elapsed, 0, sizeof(transfer_elapsed)); pv_elapsedtime_read(&cur_time); pv_elapsedtime_copy(&(info.start_time), &cur_time); @@ -450,10 +454,7 @@ int pv_watchfd_loop(pvstate_t state) * update the display. */ if (pv_elapsedtime_compare(&cur_time, &next_update) < 0) { - struct timeval tv; - tv.tv_sec = 0; - tv.tv_usec = 50000; - select(0, NULL, NULL, NULL, &tv); + pv_nanosleep(50000000); continue; } @@ -522,11 +523,11 @@ int pv_watchpid_loop(pvstate_t state) { struct pvstate_s state_copy; const char *original_format_string; - char new_format_string[512] = { 0, }; + char new_format_string[512]; struct pvwatchfd_s *info_array = NULL; struct pvstate_s *state_array = NULL; int array_length = 0; - int fd_to_idx[FD_SETSIZE] = { 0, }; + int fd_to_idx[FD_SETSIZE]; struct timespec next_update, cur_time; int idx; int prev_displayed_lines, blank_lines; @@ -553,6 +554,7 @@ int pv_watchpid_loop(pvstate_t state) * it's not present. */ original_format_string = state->format_string ? state->format_string : state->default_format; + memset(new_format_string, 0, sizeof(new_format_string)); if (NULL == strstr(original_format_string, "%N")) { (void) pv_snprintf(new_format_string, sizeof(new_format_string), "%%N %s", original_format_string); } else { @@ -606,10 +608,7 @@ int pv_watchpid_loop(pvstate_t state) * update the display. */ if (pv_elapsedtime_compare(&cur_time, &next_update) < 0) { - struct timeval tv; - tv.tv_sec = 0; - tv.tv_usec = 50000; - select(0, NULL, NULL, NULL, &tv); + pv_nanosleep(50000000); continue; } @@ -650,7 +649,7 @@ int pv_watchpid_loop(pvstate_t state) displayed_lines = 0; for (fd = 0; fd < FD_SETSIZE; fd++) { - long long position_now, transferred_since_last; + off_t position_now, transferred_since_last; struct timespec init_time, transfer_elapsed; long double elapsed_seconds; @@ -691,6 +690,9 @@ int pv_watchpid_loop(pvstate_t state) transferred_since_last = position_now - info_array[idx].position; info_array[idx].position = position_now; + memset(&init_time, 0, sizeof(init_time)); + memset(&transfer_elapsed, 0, sizeof(transfer_elapsed)); + /* * Calculate the effective start time: the time we actually * started, plus the total time we spent stopped. diff --git a/src/pv/watchpid.c b/src/pv/watchpid.c index 45bc7ae..67efa0f 100644 --- a/src/pv/watchpid.c +++ b/src/pv/watchpid.c @@ -59,7 +59,7 @@ int filesize(pvwatchfd_t info) } #ifdef __APPLE__ -int pv_watchfd_info(pvstate_t state, pvwatchfd_t info, int automatic) +int pv_watchfd_info(pvstate_t state, pvwatchfd_t info, bool automatic) { struct vnode_fdinfowithpath vnodeInfo = { }; @@ -123,11 +123,11 @@ int pv_watchfd_info(pvstate_t state, pvwatchfd_t info, int automatic) * 3 - stat or lstat on /proc/pid/fd/N failed * 4 - file descriptor is not opened on a regular file * - * If "automatic" is nonzero, then this fd was picked automatically, and so - * if it's not readable or not a regular file, no error is displayed and the + * If "automatic" is true, then this fd was picked automatically, and so if + * it's not readable or not a regular file, no error is displayed and the * function just returns an error code. */ -int pv_watchfd_info(pvstate_t state, pvwatchfd_t info, int automatic) +int pv_watchfd_info(pvstate_t state, pvwatchfd_t info, bool automatic) { if (NULL == state) return -1; @@ -403,7 +403,7 @@ int pv_watchpid_scanfds(pvstate_t state, pvstate_t pristine, continue; } #endif - rc = pv_watchfd_info(state, &(info_array[use_idx]), 1); + rc = pv_watchfd_info(state, &(info_array[use_idx]), true); /* * Lookup failed - mark this slot as being free for re-use.