An EDB customer reported a problem with pg_archivecleanup which I
have looked into and found a likely cause.  It is, in any event, a
bug which I think should be fixed.  It has to do with our use of
the readdir() function:

These are the relevant bits:

| Applications wishing to check for error situations should set
| errno to 0 before calling readdir(). If errno is set to non-zero
| on return, an error occurred.

| Upon successful completion, readdir() returns a pointer to an
| object of type struct dirent. When an error is encountered, a
| null pointer is returned and errno is set to indicate the error.
| When the end of the directory is encountered, a null pointer is
| returned and errno is not changed.

Here is our current usage:;a=blob;f=contrib/pg_archivecleanup/pg_archivecleanup.c;h=8f77998de12f95f41bb95c3e05a14de6cdf18047;hb=7800229b36d0444cf2c61f5c5895108ee5e8ee2a#l110

So an error in scanning the directory will not be reported; the
cleanup will quietly terminate the WAL deletions without processing
the remainder of the directory.  Attached is the simplest fix,
which would report the error, stop looking for WAL files, and
continue with other clean-ups. I'm not sure we should keep the fix
that simple.  We could set a flag so that we would exit with a
non-zero code, or we could try a new directory scan as long as the
last scan found and deleted at least one WAL file.  Perhaps we want
to back-patch the simple fix and do something fancier for 9.4?

I would also add a few comment lines before committing this, if we
decide to go with the simple approach -- this is for purposes of
illustration; to facilitate discussion.


Kevin Grittner
The Enterprise PostgreSQL Company
diff --git a/contrib/pg_archivecleanup/pg_archivecleanup.c b/contrib/pg_archivecleanup/pg_archivecleanup.c
index f12331a..3e47f3c 100644
--- a/contrib/pg_archivecleanup/pg_archivecleanup.c
+++ b/contrib/pg_archivecleanup/pg_archivecleanup.c
@@ -117,7 +117,7 @@ CleanupPriorWALFiles(void)
 	if ((xldir = opendir(archiveLocation)) != NULL)
-		while ((xlde = readdir(xldir)) != NULL)
+		while (errno = 0, (xlde = readdir(xldir)) != NULL)
 			strncpy(walfile, xlde->d_name, MAXPGPATH);
 			TrimExtension(walfile, additional_ext);
@@ -175,6 +175,11 @@ CleanupPriorWALFiles(void)
+		if (errno)
+			fprintf(stderr, "%s: ERROR: could not read next directory entry: %s\n",
+					progname, strerror(errno));
Sent via pgsql-hackers mailing list (
To make changes to your subscription:

Reply via email to