summaryrefslogtreecommitdiff
path: root/tools/lib/api/fd/array.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/lib/api/fd/array.c')
-rw-r--r--tools/lib/api/fd/array.c17
1 files changed, 13 insertions, 4 deletions
diff --git a/tools/lib/api/fd/array.c b/tools/lib/api/fd/array.c
index f0f195207fca..67b73481df27 100644
--- a/tools/lib/api/fd/array.c
+++ b/tools/lib/api/fd/array.c
@@ -31,7 +31,8 @@ int fdarray__grow(struct fdarray *fda, int nr)
priv = realloc(fda->priv, psize);
if (priv == NULL) {
- free(entries);
+ /* this will be freed by fdarray__exit() */
+ fda->entries = entries;
return -ENOMEM;
}
@@ -50,7 +51,7 @@ struct fdarray *fdarray__new(int nr_alloc, int nr_autogrow)
if (fda != NULL) {
if (fdarray__grow(fda, nr_alloc)) {
- free(fda);
+ fdarray__delete(fda);
fda = NULL;
} else {
fda->nr_autogrow = nr_autogrow;
@@ -115,6 +116,9 @@ int fdarray__filter(struct fdarray *fda, short revents,
return 0;
for (fd = 0; fd < fda->nr; ++fd) {
+ if (fda->priv[fd].flags & fdarray_flag__nonfilterable)
+ continue;
+
if (!fda->entries[fd].events)
continue;
@@ -122,12 +126,17 @@ int fdarray__filter(struct fdarray *fda, short revents,
if (entry_destructor)
entry_destructor(fda, fd, arg);
+ /*
+ * Set fd to -1 so poll() ignores this entry; otherwise
+ * POLLHUP/POLLERR are still reported for events=0 fds
+ * (POSIX: always checked), causing a poll storm.
+ */
+ fda->entries[fd].fd = -1;
fda->entries[fd].revents = fda->entries[fd].events = 0;
continue;
}
- if (!(fda->priv[fd].flags & fdarray_flag__nonfilterable))
- ++nr;
+ ++nr;
}
return nr;