[PATCH app/xlsatoms 3/3] Always use chunks when retrieving atoms.

Tobias Stoeckmann tobias at stoeckmann.org
Wed Jul 4 13:29:58 UTC 2018


If a low and high range limit has been specified, all atoms are
retrieved at once. This is also the reason why malloc() is used:
All cookies are stored before collecting the data.

By using chunks it is possible to specify a huge range or even
all possible atoms without running out of memory.

Signed-off-by: Tobias Stoeckmann <tobias at stoeckmann.org>
---
 xlsatoms.c | 51 ++++++++++++++-------------------------------------
 1 file changed, 14 insertions(+), 37 deletions(-)

diff --git a/xlsatoms.c b/xlsatoms.c
index 5bed0cc..a971901 100644
--- a/xlsatoms.c
+++ b/xlsatoms.c
@@ -234,7 +234,7 @@ do_range(xcb_connection_t *c, const char *format, char *range)
 }
 
 static int
-say_batch(xcb_connection_t *c, const char *format, xcb_get_atom_name_cookie_t *cookie, xcb_atom_t low, long count)
+say_batch(xcb_connection_t *c, const char *format, xcb_get_atom_name_cookie_t *cookie, xcb_atom_t low, long count, int stop_error)
 {
     xcb_generic_error_t *e;
     char atom_name[1024];
@@ -248,7 +248,7 @@ say_batch(xcb_connection_t *c, const char *format, xcb_get_atom_name_cookie_t *c
 	xcb_get_atom_name_reply_t *r;
 	r = xcb_get_atom_name_reply(c, cookie[i], &e);
 	if (r) {
-	    if (!done) {
+	    if (!done || !stop_error) {
 		/* We could just use %.*s in 'format', but we want to be compatible
 		   with legacy command line usage */
 		snprintf(atom_name, sizeof(atom_name), "%.*s",
@@ -265,50 +265,27 @@ say_batch(xcb_connection_t *c, const char *format, xcb_get_atom_name_cookie_t *c
 	}
     }
 
-    return done;
+    return done && stop_error;
 }
 
 static void
 list_atoms(xcb_connection_t *c, const char *format, int mask, xcb_atom_t low, xcb_atom_t high)
 {
-    xcb_get_atom_name_cookie_t *cookie_jar;
+    xcb_get_atom_name_cookie_t cookie_jar[ATOMS_PER_BATCH];
     int done = 0;
+    long count;
 
-    switch (mask) {
-      case RangeHigh:
+    if ((mask & RangeLow) == 0)
 	low = 1;
-	/* fall through */
-      case (RangeLow | RangeHigh):
-	if (high - low >= SIZE_MAX / sizeof(xcb_get_atom_name_cookie_t)) {
-	    fprintf(stderr, "Cannot allocate space for %lu atom requests\n", (unsigned long) (high - low));
-	    return;
-	}
-	cookie_jar = malloc((high - low + 1) * sizeof(xcb_get_atom_name_cookie_t));
-        if (!cookie_jar) {
-	    fprintf(stderr, "Out of memory allocating space for %lu atom requests\n", (unsigned long) (high - low));
-	    return;
-	}
+    if ((mask & RangeHigh) == 0)
+	high = UINT32_MAX;
 
-	say_batch(c, format, cookie_jar, low, high - low + 1);
-	free(cookie_jar);
-	break;
-
-      default:
-	low = 1;
-	/* fall through */
-      case RangeLow:
-	cookie_jar = malloc(ATOMS_PER_BATCH * sizeof(xcb_get_atom_name_cookie_t));
-        if (!cookie_jar) {
-	    fprintf(stderr, "Out of memory allocating space for %ld atom requests\n", (long) ATOMS_PER_BATCH);
-	    return;
-	}
-	while (!done) {
-	    done = say_batch(c, format, cookie_jar, low, ATOMS_PER_BATCH);
-	    low += ATOMS_PER_BATCH;
+    while (!done) {
+	count = high - low < ATOMS_PER_BATCH - 1 ? high - low + 1 : ATOMS_PER_BATCH;
+	done = say_batch(c, format, cookie_jar, low, count, (mask & RangeHigh) == 0);
+	if (high - low < UINT32_MAX && low == high - count + 1) {
+	    done = 1;
 	}
-	free(cookie_jar);
-	break;
+	low += count;
     }
-
-    return;
 }
-- 
2.18.0



More information about the xorg-devel mailing list