On Wed, Feb 1, 2023 at 6:28 AM Justin Pryzby <pry...@telsasoft.com> wrote:
> > I pushed the rmtree() change.  Let's see if that helps, or tells us
> > something new.
>
> I found a few failures since then:
>
> https://api.cirrus-ci.com/v1/artifact/task/6696942420361216/testrun/build/testrun/pg_upgrade/002_pg_upgrade/log/regress_log_002_pg_upgrade
>
> pg_upgrade: warning: could not remove directory 
> "C:/cirrus/build/testrun/pg_upgrade/002_pg_upgrade/data/t_002_pg_upgrade_new_node_data/pgdata/pg_upgrade_output.d/20230131T134931.720/log":
>  Directory not empty
> pg_upgrade: warning: could not remove directory 
> "C:/cirrus/build/testrun/pg_upgrade/002_pg_upgrade/data/t_002_pg_upgrade_new_node_data/pgdata/pg_upgrade_output.d/20230131T134931.720":
>  Directory not empty

So no change: we didn't see "could not unlink file ...".  So I think
that means that it was rmtree() that unlinked the file for the *first*
time, but someone else has it open.

Even though Windows is at this point eroding my love of computers and
making me consider a new career in, I dunno, carrot farming or
something, I have one more idea.  Check out this kluge in
src/bin/pg_upgrade/exec.c:

        /*
         * "pg_ctl -w stop" might have reported that the server has stopped
         * because the postmaster.pid file has been removed, but "pg_ctl -w
         * start" might still be in the process of closing and might still be
         * holding its stdout and -l log file descriptors open.  Therefore,
         * try to open the log file a few more times.
         */

I'm not sure about anything, but if that's what's happening here, then
maybe the attached would help.  In short, it would make the previous
theory true (the idea of a second unlink() saving the day).
diff --git a/src/bin/pg_upgrade/util.c b/src/bin/pg_upgrade/util.c
index 42dcbfc5b5..f214b7737f 100644
--- a/src/bin/pg_upgrade/util.c
+++ b/src/bin/pg_upgrade/util.c
@@ -68,7 +68,12 @@ cleanup_output_dirs(void)
 	if (log_opts.retain)
 		return;
 
-	(void) rmtree(log_opts.basedir, true);
+	/*
+	 * Try twice.  The second time might wait for files to be concurrently
+	 * closed on Windows.
+	 */
+	if (!rmtree(log_opts.basedir, true))
+		rmtree(log_opts.basedir, true);
 
 	/* Remove pg_upgrade_output.d only if empty */
 	switch (pg_check_dir(log_opts.rootdir))
@@ -80,7 +85,12 @@ cleanup_output_dirs(void)
 
 		case 1:					/* exists and empty */
 		case 2:					/* exists and contains only dot files */
-			(void) rmtree(log_opts.rootdir, true);
+			/*
+			 * Try twice.  The second time might wait for files to be
+			 * concurrently closed on Windows.
+			 */
+			if (!rmtree(log_opts.rootdir, true))
+				rmtree(log_opts.rootdir, true);
 			break;
 
 		case 4:					/* exists */

Reply via email to