Eliminate the fd_to_idx array in --watchfd, so that file descriptors aren't constrained to FD_SETSIZE and so we don't have to track another array.
This commit is contained in:
@@ -619,7 +619,7 @@ int pv_remote_set(pvstate_t);
|
||||
int pv_watchfd_info(pvstate_t, pvwatchfd_t, bool);
|
||||
bool pv_watchfd_changed(pvwatchfd_t);
|
||||
off_t pv_watchfd_position(pvwatchfd_t);
|
||||
int pv_watchpid_scanfds(pvstate_t, pid_t, int *, pvwatchfd_t *, int *);
|
||||
int pv_watchpid_scanfds(pvstate_t, pid_t, int *, pvwatchfd_t *);
|
||||
void pv_watchpid_setname(pvstate_t, pvwatchfd_t);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
+12
-24
@@ -779,7 +779,6 @@ int pv_watchpid_loop(pvstate_t state)
|
||||
char new_format_string[512]; /* flawfinder: ignore */
|
||||
struct pvwatchfd_s *info_array = NULL;
|
||||
int array_length = 0;
|
||||
int fd_to_idx[FD_SETSIZE];
|
||||
struct timespec next_update, cur_time;
|
||||
int idx;
|
||||
int prev_displayed_lines, blank_lines;
|
||||
@@ -845,14 +844,10 @@ int pv_watchpid_loop(pvstate_t state)
|
||||
pv_elapsedtime_copy(&next_update, &cur_time);
|
||||
pv_elapsedtime_add_nsec(&next_update, (long long) (1000000000.0 * state->control.interval));
|
||||
|
||||
for (idx = 0; idx < FD_SETSIZE; idx++) {
|
||||
fd_to_idx[idx] = -1;
|
||||
}
|
||||
|
||||
prev_displayed_lines = 0;
|
||||
|
||||
while (true) {
|
||||
int rc, fd, displayed_lines;
|
||||
int rc, displayed_lines;
|
||||
|
||||
if (1 == state->flags.trigger_exit)
|
||||
break;
|
||||
@@ -909,7 +904,7 @@ int pv_watchpid_loop(pvstate_t state)
|
||||
}
|
||||
}
|
||||
|
||||
rc = pv_watchpid_scanfds(state, state->watchfd.pid[0], &array_length, &info_array, fd_to_idx);
|
||||
rc = pv_watchpid_scanfds(state, state->watchfd.pid[0], &array_length, &info_array);
|
||||
if (rc != 0) {
|
||||
if (first_pass) {
|
||||
pv_error("%s %u: %s", _("pid"), state->watchfd.pid[0], strerror(errno));
|
||||
@@ -924,40 +919,34 @@ int pv_watchpid_loop(pvstate_t state)
|
||||
first_pass = false;
|
||||
displayed_lines = 0;
|
||||
|
||||
for (fd = 0; fd < FD_SETSIZE && NULL != info_array; fd++) {
|
||||
for (idx = 0; NULL != info_array && idx < array_length; idx++) {
|
||||
off_t position_now;
|
||||
struct timespec init_time, transfer_elapsed;
|
||||
|
||||
/* Skip unused array entries. */
|
||||
if (info_array[idx].unused)
|
||||
continue;
|
||||
|
||||
/* No more lines if we've filled the display. */
|
||||
if (displayed_lines >= (int) (state->control.height))
|
||||
break;
|
||||
|
||||
idx = fd_to_idx[fd];
|
||||
|
||||
if (idx < 0)
|
||||
continue;
|
||||
|
||||
if (info_array[idx].unused) {
|
||||
debug("%s %d: %s", "fd", fd, "unused array entry - skipping");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!info_array[idx].displayable) {
|
||||
/*
|
||||
* Non-displayable fd - just remove if
|
||||
* changed
|
||||
*/
|
||||
if (pv_watchfd_changed(&(info_array[idx]))) {
|
||||
fd_to_idx[fd] = -1;
|
||||
debug("%s %d: %s", "fd", info_array[idx].watch_fd, "removing");
|
||||
info_array[idx].unused = true;
|
||||
info_array[idx].displayable = false;
|
||||
pv_freecontents_watchfd(&(info_array[idx]));
|
||||
debug("%s %d: %s", "fd", fd, "removing");
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (info_array[idx].watch_fd < 0) {
|
||||
debug("%s %d: %s", "fd", fd, "negative fd - skipping");
|
||||
debug("%s %d: %s", "fd", info_array[idx].watch_fd, "negative fd - skipping");
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -968,11 +957,10 @@ int pv_watchpid_loop(pvstate_t state)
|
||||
position_now = pv_watchfd_position(&(info_array[idx]));
|
||||
|
||||
if (position_now < 0) {
|
||||
fd_to_idx[fd] = -1;
|
||||
debug("%s %d: %s", "fd", info_array[idx].watch_fd, "removing");
|
||||
info_array[idx].unused = true;
|
||||
info_array[idx].displayable = false;
|
||||
pv_freecontents_watchfd(&(info_array[idx]));
|
||||
debug("%s %d: %s", "fd", fd, "removing");
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -1000,7 +988,7 @@ int pv_watchpid_loop(pvstate_t state)
|
||||
pv_tty_write(&(state->flags), "\n", 1);
|
||||
}
|
||||
|
||||
debug("%s %d [%d]: %Lf / %Ld", "fd", fd, idx,
|
||||
debug("%s %d [%d]: %Lf / %Ld", "fd", info_array[idx].watch_fd, idx,
|
||||
info_array[idx].transfer.elapsed_seconds, position_now);
|
||||
|
||||
if (info_array[idx].watch_fd >= 0) {
|
||||
|
||||
+49
-14
@@ -394,6 +394,28 @@ void pv_freecontents_watchfd(pvwatchfd_t info)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Comparison function for qsort, to compare two pvwatchfd_s structures.
|
||||
*/
|
||||
static int pv_compare_watchfd(const void *a, const void *b)
|
||||
{
|
||||
int fd_a, fd_b;
|
||||
|
||||
fd_a = 0;
|
||||
fd_b = 0;
|
||||
if (NULL != a)
|
||||
fd_a = ((pvwatchfd_t) a)->watch_fd;
|
||||
if (NULL != b)
|
||||
fd_b = ((pvwatchfd_t) b)->watch_fd;
|
||||
|
||||
if (fd_a < fd_b)
|
||||
return -1;
|
||||
if (fd_a > fd_b)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Scan the given process and update the arrays with any new file
|
||||
* descriptors.
|
||||
@@ -401,8 +423,7 @@ void pv_freecontents_watchfd(pvwatchfd_t info)
|
||||
* Returns 0 on success, 1 if the process no longer exists or could not be
|
||||
* read, or 2 for a memory allocation error.
|
||||
*/
|
||||
int pv_watchpid_scanfds(pvstate_t state,
|
||||
pid_t watch_pid, int *array_length_ptr, pvwatchfd_t * info_array_ptr, int *fd_to_idx)
|
||||
int pv_watchpid_scanfds(pvstate_t state, pid_t watch_pid, int *array_length_ptr, pvwatchfd_t * info_array_ptr)
|
||||
{
|
||||
int array_length = 0;
|
||||
struct pvwatchfd_s *info_array = NULL;
|
||||
@@ -419,6 +440,7 @@ int pv_watchpid_scanfds(pvstate_t state,
|
||||
char fd_dir[512]; /* flawfinder: ignore - zeroed, bounded with pv_snprintf(). */
|
||||
DIR *dptr;
|
||||
struct dirent *d;
|
||||
bool changes_made;
|
||||
|
||||
memset(fd_dir, 0, sizeof(fd_dir));
|
||||
(void) pv_snprintf(fd_dir, sizeof(fd_dir), "/proc/%u/fd", watch_pid);
|
||||
@@ -431,6 +453,8 @@ int pv_watchpid_scanfds(pvstate_t state,
|
||||
array_length = *array_length_ptr;
|
||||
info_array = *info_array_ptr;
|
||||
|
||||
changes_made = false;
|
||||
|
||||
#ifdef __APPLE__
|
||||
if (fd_infos_count < 1) {
|
||||
pv_error("%s: no fds found", _("pid"));
|
||||
@@ -440,7 +464,7 @@ int pv_watchpid_scanfds(pvstate_t state,
|
||||
#else
|
||||
while ((d = readdir(dptr)) != NULL) {
|
||||
#endif
|
||||
int fd, check_idx, use_idx, rc;
|
||||
int fd, check_idx, found_idx, use_idx, rc;
|
||||
off_t position_now;
|
||||
|
||||
fd = -1;
|
||||
@@ -451,21 +475,24 @@ int pv_watchpid_scanfds(pvstate_t state,
|
||||
continue;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* TODO: determine whether fd_to_idx really helps here,
|
||||
* since it constrains us to fds < FD_SETSIZE.
|
||||
*/
|
||||
|
||||
/* Skip if the fd is outside the array. */
|
||||
if ((fd < 0) || (fd >= FD_SETSIZE))
|
||||
/* Skip if the fd is negative. */
|
||||
if (fd < 0)
|
||||
continue;
|
||||
|
||||
/*
|
||||
* Skip if this fd is already known to us.
|
||||
*/
|
||||
if (fd_to_idx[fd] != -1) {
|
||||
continue;
|
||||
found_idx = -1;
|
||||
for (check_idx = 0; check_idx < array_length; check_idx++) {
|
||||
if (info_array[check_idx].unused)
|
||||
continue;
|
||||
if (info_array[check_idx].watch_fd != fd)
|
||||
continue;
|
||||
found_idx = check_idx;
|
||||
break;
|
||||
}
|
||||
if (found_idx >= 0)
|
||||
continue;
|
||||
|
||||
/*
|
||||
* See if there's an empty slot we can re-use.
|
||||
@@ -491,6 +518,8 @@ int pv_watchpid_scanfds(pvstate_t state,
|
||||
|
||||
debug("%s: %d => index %d", "found new fd", fd, use_idx);
|
||||
|
||||
changes_made = true;
|
||||
|
||||
/*
|
||||
* Initialise the details of this new entry.
|
||||
*/
|
||||
@@ -528,8 +557,6 @@ int pv_watchpid_scanfds(pvstate_t state,
|
||||
continue;
|
||||
}
|
||||
|
||||
fd_to_idx[fd] = use_idx;
|
||||
|
||||
/*
|
||||
* Not displayable - mark it as such so the main loop
|
||||
* doesn't show it.
|
||||
@@ -568,6 +595,14 @@ int pv_watchpid_scanfds(pvstate_t state,
|
||||
(void) closedir(dptr);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* If any changes were made (i.e. new file descriptors were found),
|
||||
* sort the array so that file descriptors are always displayed in
|
||||
* ascending numerical order.
|
||||
*/
|
||||
if (changes_made && NULL != info_array && array_length > 1)
|
||||
qsort(info_array, (size_t) array_length, sizeof(info_array[0]), pv_compare_watchfd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user