Обсуждение: pg_upgrade and log file output on Windows

Поиск
Список
Период
Сортировка

pg_upgrade and log file output on Windows

От
Bruce Momjian
Дата:
Has anyone successfully used pg_upgrade 9.0 with -l (log) on Windows?

I received a private email bug report that pg_upgrade 9.0 does not work
with the -l/log option on Windows.  The error is:
Analyzing all rows in the new cluster""c:/MinGW/msys/1.0/home/edb/inst/bin/vacuumdb" --port 55445 --username "edb"
--all--analyze>> c:/MinGW/msys/1.0/home/edb/auxschedule/test.log 2>&1"The process cannot access the file because it is
beingused by anotherprocess.
 

What has me confused is this same code exists in pg_migrator, which was
fixed to work with -l on Windows by Hiroshi Saito with this change:
    /*     * On Win32, we can't send both server output and pg_ctl output     * to the same file because we get the
error:    * "The process cannot access the file because it is being used by another process."     * so we have to send
pg_ctloutput to 'nul'.     */    sprintf(cmd, SYSTEMQUOTE "\"%s/pg_ctl\" -l \"%s\" -D \"%s\" "    "-o \"-p %d -c
autovacuum=off-c autovacuum_freeze_max_age=2000000000\" "            "start >> \"%s\" 2>&1" SYSTEMQUOTE,
bindir,ctx->logfile, datadir, port,#ifndef WIN32             ctx->logfile);#else             DEVNULL);#endif
 

The fix was not to use the same log file and output file for pg_ctl. 
But as you can see, the pg_ctl and vacuumdb code is unchanged:
   prep_status(ctx, "Analyzing all rows in the new cluster");   exec_prog(ctx, true,             SYSTEMQUOTE
"\"%s/vacuumdb\"--port %d --username \"%s\" "             "--all --analyze >> %s 2>&1" SYSTEMQUOTE,
ctx->new.bindir,ctx->new.port, ctx->user, ctx->logfile);
 

I can't figure out of there is something odd about this user's setup or
if there is a bug in pg_upgrade with -l on Windows.

--  Bruce Momjian  <bruce@momjian.us>        http://momjian.us EnterpriseDB
http://enterprisedb.com
 + It's impossible for everything to be true. +


Re: pg_upgrade and log file output on Windows

От
"Andrew Dunstan"
Дата:
On Mon, July 18, 2011 11:28 pm, Bruce Momjian wrote:
> Has anyone successfully used pg_upgrade 9.0 with -l (log) on Windows?
>
> I received a private email bug report that pg_upgrade 9.0 does not work
> with the -l/log option on Windows.  The error is:
>
>     Analyzing all rows in the new cluster
>     ""c:/MinGW/msys/1.0/home/edb/inst/bin/vacuumdb" --port 55445 --username
> "edb" --all --analyze
>     >> c:/MinGW/msys/1.0/home/edb/auxschedule/test.log 2>&1"
>     The process cannot access the file because it is being used by another
>     process.
>
> What has me confused is this same code exists in pg_migrator, which was
> fixed to work with -l on Windows by Hiroshi Saito with this change:
>
>         /*
>          * On Win32, we can't send both server output and pg_ctl output
>          * to the same file because we get the error:
>          * "The process cannot access the file because it is being used by
> another process."
>          * so we have to send pg_ctl output to 'nul'.
>          */
>         sprintf(cmd, SYSTEMQUOTE "\"%s/pg_ctl\" -l \"%s\" -D \"%s\" "
>         "-o \"-p %d -c autovacuum=off -c
> autovacuum_freeze_max_age=2000000000\" "
>                 "start >> \"%s\" 2>&1" SYSTEMQUOTE,
>                  bindir, ctx->logfile, datadir, port,
>     #ifndef WIN32
>                  ctx->logfile);
>     #else
>                  DEVNULL);
>     #endif
>
> The fix was not to use the same log file and output file for pg_ctl.
> But as you can see, the pg_ctl and vacuumdb code is unchanged:
>
>     prep_status(ctx, "Analyzing all rows in the new cluster");
>     exec_prog(ctx, true,
>               SYSTEMQUOTE "\"%s/vacuumdb\" --port %d --username \"%s\" "
>               "--all --analyze >> %s 2>&1" SYSTEMQUOTE,
>               ctx->new.bindir, ctx->new.port, ctx->user, ctx->logfile);
>
> I can't figure out of there is something odd about this user's setup or
> if there is a bug in pg_upgrade with -l on Windows.
>


The Windows file system seems to have some asynchronicity regarding what
files are locked. For that reason, the buildfarm code has long had a
couple of "sleep(5)" calls where it calls pg_ctl. You might benefit from
doing something similar.

cheers

andrew.



Re: pg_upgrade and log file output on Windows

От
Bruce Momjian
Дата:
Andrew Dunstan wrote:
> > I can't figure out of there is something odd about this user's setup or
> > if there is a bug in pg_upgrade with -l on Windows.
> >
> 
> 
> The Windows file system seems to have some asynchronicity regarding what
> files are locked. For that reason, the buildfarm code has long had a
> couple of "sleep(5)" calls where it calls pg_ctl. You might benefit from
> doing something similar.

Wow, I had no idea --- I can certainly add them.  It is possible the
person testing this has a faster machine than other users.  I will
report back after testing with a sleep(5).

--  Bruce Momjian  <bruce@momjian.us>        http://momjian.us EnterpriseDB
http://enterprisedb.com
 + It's impossible for everything to be true. +


Re: pg_upgrade and log file output on Windows

От
Andrew Dunstan
Дата:

On 07/19/2011 01:25 PM, Bruce Momjian wrote:
> Andrew Dunstan wrote:
>>> I can't figure out of there is something odd about this user's setup or
>>> if there is a bug in pg_upgrade with -l on Windows.
>>>
>>
>> The Windows file system seems to have some asynchronicity regarding what
>> files are locked. For that reason, the buildfarm code has long had a
>> couple of "sleep(5)" calls where it calls pg_ctl. You might benefit from
>> doing something similar.
> Wow, I had no idea --- I can certainly add them.  It is possible the
> person testing this has a faster machine than other users.  I will
> report back after testing with a sleep(5).


We need to work out a way to get pg_upgrade testing into the buildfarm. 
It's becoming too important not to.

cheers

andrew


Re: pg_upgrade and log file output on Windows

От
Bruce Momjian
Дата:
I have fixed the bug below with the attached patches for 9.0, 9.1, and
9.2.  I did a minimal patch for 9.0 and 9.1, and a more thorough patch
for 9.2.

The use of -l/log was tested originally in pg_migrator (for 8.4) and
reported to be working, but it turns out it only worked in 'check' mode,
and threw an error during actual upgrade.  This bug was reported to me
recently by EnterpriseDB testing of PG 9.0 on Windows.  The 9.2 C
comments should make it clear that Windows doesn't allow multiple
processes to write to the same file and  should avoid future breakage.

---------------------------------------------------------------------------

Bruce Momjian wrote:
> Has anyone successfully used pg_upgrade 9.0 with -l (log) on Windows?
>
> I received a private email bug report that pg_upgrade 9.0 does not work
> with the -l/log option on Windows.  The error is:
>
>     Analyzing all rows in the new cluster
>     ""c:/MinGW/msys/1.0/home/edb/inst/bin/vacuumdb" --port 55445 --username "edb" --all --analyze
>     >> c:/MinGW/msys/1.0/home/edb/auxschedule/test.log 2>&1"
>     The process cannot access the file because it is being used by another
>     process.
>
> What has me confused is this same code exists in pg_migrator, which was
> fixed to work with -l on Windows by Hiroshi Saito with this change:
>
>         /*
>          * On Win32, we can't send both server output and pg_ctl output
>          * to the same file because we get the error:
>          * "The process cannot access the file because it is being used by another process."
>          * so we have to send pg_ctl output to 'nul'.
>          */
>         sprintf(cmd, SYSTEMQUOTE "\"%s/pg_ctl\" -l \"%s\" -D \"%s\" "
>         "-o \"-p %d -c autovacuum=off -c autovacuum_freeze_max_age=2000000000\" "
>                 "start >> \"%s\" 2>&1" SYSTEMQUOTE,
>                  bindir, ctx->logfile, datadir, port,
>     #ifndef WIN32
>                  ctx->logfile);
>     #else
>                  DEVNULL);
>     #endif
>
> The fix was not to use the same log file and output file for pg_ctl.
> But as you can see, the pg_ctl and vacuumdb code is unchanged:
>
>     prep_status(ctx, "Analyzing all rows in the new cluster");
>     exec_prog(ctx, true,
>               SYSTEMQUOTE "\"%s/vacuumdb\" --port %d --username \"%s\" "
>               "--all --analyze >> %s 2>&1" SYSTEMQUOTE,
>               ctx->new.bindir, ctx->new.port, ctx->user, ctx->logfile);
>
> I can't figure out of there is something odd about this user's setup or
> if there is a bug in pg_upgrade with -l on Windows.
>
> --
>   Bruce Momjian  <bruce@momjian.us>        http://momjian.us
>   EnterpriseDB                             http://enterprisedb.com
>
>   + It's impossible for everything to be true. +
>
> --
> Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
> To make changes to your subscription:
> http://www.postgresql.org/mailpref/pgsql-hackers

--
  Bruce Momjian  <bruce@momjian.us>        http://momjian.us
  EnterpriseDB                             http://enterprisedb.com

  + It's impossible for everything to be true. +
diff --git a/contrib/pg_upgrade/pg_upgrade.c b/contrib/pg_upgrade/pg_upgrade.c
new file mode 100644
index 1a515e7..37d2eed
*** a/contrib/pg_upgrade/pg_upgrade.c
--- b/contrib/pg_upgrade/pg_upgrade.c
*************** prepare_new_cluster(migratorContext *ctx
*** 161,168 ****
      prep_status(ctx, "Analyzing all rows in the new cluster");
      exec_prog(ctx, true,
                SYSTEMQUOTE "\"%s/vacuumdb\" --port %d --username \"%s\" "
!               "--all --analyze >> %s 2>&1" SYSTEMQUOTE,
!               ctx->new.bindir, ctx->new.port, ctx->user, ctx->logfile);
      check_ok(ctx);

      /*
--- 161,174 ----
      prep_status(ctx, "Analyzing all rows in the new cluster");
      exec_prog(ctx, true,
                SYSTEMQUOTE "\"%s/vacuumdb\" --port %d --username \"%s\" "
!               "--all --analyze >> \"%s\" 2>&1" SYSTEMQUOTE,
!               ctx->new.bindir, ctx->new.port, ctx->user,
! #ifndef WIN32
!               ctx->logfile
! #else
!               DEVNULL
! #endif
!               );
      check_ok(ctx);

      /*
*************** prepare_new_cluster(migratorContext *ctx
*** 174,181 ****
      prep_status(ctx, "Freezing all rows on the new cluster");
      exec_prog(ctx, true,
                SYSTEMQUOTE "\"%s/vacuumdb\" --port %d --username \"%s\" "
!               "--all --freeze >> %s 2>&1" SYSTEMQUOTE,
!               ctx->new.bindir, ctx->new.port, ctx->user, ctx->logfile);
      check_ok(ctx);

      get_pg_database_relfilenode(ctx, CLUSTER_NEW);
--- 180,193 ----
      prep_status(ctx, "Freezing all rows on the new cluster");
      exec_prog(ctx, true,
                SYSTEMQUOTE "\"%s/vacuumdb\" --port %d --username \"%s\" "
!               "--all --freeze >> \"%s\" 2>&1" SYSTEMQUOTE,
!               ctx->new.bindir, ctx->new.port, ctx->user,
! #ifndef WIN32
!               ctx->logfile
! #else
!               DEVNULL
! #endif
!               );
      check_ok(ctx);

      get_pg_database_relfilenode(ctx, CLUSTER_NEW);
*************** prepare_new_databases(migratorContext *c
*** 207,213 ****
                "--no-psqlrc --port %d --username \"%s\" "
                "-f \"%s/%s\" --dbname template1 >> \"%s\"" SYSTEMQUOTE,
                ctx->new.bindir, ctx->new.port, ctx->user, ctx->cwd,
!               GLOBALS_DUMP_FILE, ctx->logfile);
      check_ok(ctx);

      get_db_and_rel_infos(ctx, &ctx->new.dbarr, CLUSTER_NEW);
--- 219,231 ----
                "--no-psqlrc --port %d --username \"%s\" "
                "-f \"%s/%s\" --dbname template1 >> \"%s\"" SYSTEMQUOTE,
                ctx->new.bindir, ctx->new.port, ctx->user, ctx->cwd,
!               GLOBALS_DUMP_FILE,
! #ifndef WIN32
!               ctx->logfile
! #else
!               DEVNULL
! #endif
!               );
      check_ok(ctx);

      get_db_and_rel_infos(ctx, &ctx->new.dbarr, CLUSTER_NEW);
*************** create_new_objects(migratorContext *ctx)
*** 230,236 ****
                "--no-psqlrc --port %d --username \"%s\" "
                "-f \"%s/%s\" --dbname template1 >> \"%s\"" SYSTEMQUOTE,
                ctx->new.bindir, ctx->new.port, ctx->user, ctx->cwd,
!               DB_DUMP_FILE, ctx->logfile);
      check_ok(ctx);

      /* regenerate now that we have db schemas */
--- 248,260 ----
                "--no-psqlrc --port %d --username \"%s\" "
                "-f \"%s/%s\" --dbname template1 >> \"%s\"" SYSTEMQUOTE,
                ctx->new.bindir, ctx->new.port, ctx->user, ctx->cwd,
!               DB_DUMP_FILE,
! #ifndef WIN32
!               ctx->logfile
! #else
!               DEVNULL
! #endif
!               );
      check_ok(ctx);

      /* regenerate now that we have db schemas */
*************** copy_clog_xlog_xid(migratorContext *ctx)
*** 282,288 ****
      exec_prog(ctx, true, SYSTEMQUOTE "\"%s/pg_resetxlog\" -l %u,%u,%u \"%s\" >> \"%s\" 2>&1" SYSTEMQUOTE,
                ctx->new.bindir, ctx->old.controldata.chkpnt_tli,
                ctx->old.controldata.logid, ctx->old.controldata.nxtlogseg,
!               ctx->new.pgdata, ctx->logfile);
      check_ok(ctx);
  }

--- 306,318 ----
      exec_prog(ctx, true, SYSTEMQUOTE "\"%s/pg_resetxlog\" -l %u,%u,%u \"%s\" >> \"%s\" 2>&1" SYSTEMQUOTE,
                ctx->new.bindir, ctx->old.controldata.chkpnt_tli,
                ctx->old.controldata.logid, ctx->old.controldata.nxtlogseg,
!               ctx->new.pgdata,
! #ifndef WIN32
!               ctx->logfile
! #else
!               DEVNULL
! #endif
!               );
      check_ok(ctx);
  }

diff --git a/contrib/pg_upgrade/pg_upgrade.c b/contrib/pg_upgrade/pg_upgrade.c
new file mode 100644
index e329dc3..abd3d5f
*** a/contrib/pg_upgrade/pg_upgrade.c
--- b/contrib/pg_upgrade/pg_upgrade.c
*************** prepare_new_cluster(void)
*** 193,200 ****
      prep_status("Analyzing all rows in the new cluster");
      exec_prog(true,
                SYSTEMQUOTE "\"%s/vacuumdb\" --port %d --username \"%s\" "
!               "--all --analyze >> %s 2>&1" SYSTEMQUOTE,
!       new_cluster.bindir, new_cluster.port, os_info.user, log_opts.filename);
      check_ok();

      /*
--- 193,206 ----
      prep_status("Analyzing all rows in the new cluster");
      exec_prog(true,
                SYSTEMQUOTE "\"%s/vacuumdb\" --port %d --username \"%s\" "
!               "--all --analyze >> \"%s\" 2>&1" SYSTEMQUOTE,
!       new_cluster.bindir, new_cluster.port, os_info.user,
! #ifndef WIN32
!       log_opts.filename
! #else
!       DEVNULL
! #endif
!       );
      check_ok();

      /*
*************** prepare_new_cluster(void)
*** 206,213 ****
      prep_status("Freezing all rows on the new cluster");
      exec_prog(true,
                SYSTEMQUOTE "\"%s/vacuumdb\" --port %d --username \"%s\" "
!               "--all --freeze >> %s 2>&1" SYSTEMQUOTE,
!       new_cluster.bindir, new_cluster.port, os_info.user, log_opts.filename);
      check_ok();

      get_pg_database_relfilenode(&new_cluster);
--- 212,225 ----
      prep_status("Freezing all rows on the new cluster");
      exec_prog(true,
                SYSTEMQUOTE "\"%s/vacuumdb\" --port %d --username \"%s\" "
!               "--all --freeze >> \"%s\" 2>&1" SYSTEMQUOTE,
!       new_cluster.bindir, new_cluster.port, os_info.user,
! #ifndef WIN32
!       log_opts.filename
! #else
!       DEVNULL
! #endif
!       );
      check_ok();

      get_pg_database_relfilenode(&new_cluster);
*************** prepare_new_databases(void)
*** 245,251 ****
                "--no-psqlrc --port %d --username \"%s\" "
                "-f \"%s/%s\" --dbname template1 >> \"%s\"" SYSTEMQUOTE,
                new_cluster.bindir, new_cluster.port, os_info.user, os_info.cwd,
!               GLOBALS_DUMP_FILE, log_opts.filename);
      check_ok();

      /* we load this to get a current list of databases */
--- 257,269 ----
                "--no-psqlrc --port %d --username \"%s\" "
                "-f \"%s/%s\" --dbname template1 >> \"%s\"" SYSTEMQUOTE,
                new_cluster.bindir, new_cluster.port, os_info.user, os_info.cwd,
!               GLOBALS_DUMP_FILE,
! #ifndef WIN32
!               log_opts.filename
! #else
!               DEVNULL
! #endif
!               );
      check_ok();

      /* we load this to get a current list of databases */
*************** create_new_objects(void)
*** 276,282 ****
                "--no-psqlrc --port %d --username \"%s\" "
                "-f \"%s/%s\" --dbname template1 >> \"%s\"" SYSTEMQUOTE,
                new_cluster.bindir, new_cluster.port, os_info.user, os_info.cwd,
!               DB_DUMP_FILE, log_opts.filename);
      check_ok();

      /* regenerate now that we have objects in the databases */
--- 294,306 ----
                "--no-psqlrc --port %d --username \"%s\" "
                "-f \"%s/%s\" --dbname template1 >> \"%s\"" SYSTEMQUOTE,
                new_cluster.bindir, new_cluster.port, os_info.user, os_info.cwd,
!               DB_DUMP_FILE,
! #ifndef WIN32
!               log_opts.filename
! #else
!               DEVNULL
! #endif
!               );
      check_ok();

      /* regenerate now that we have objects in the databases */
*************** copy_clog_xlog_xid(void)
*** 324,330 ****
      exec_prog(true, SYSTEMQUOTE "\"%s/pg_resetxlog\" -l %u,%u,%u \"%s\" >> \"%s\" 2>&1" SYSTEMQUOTE,
                new_cluster.bindir, old_cluster.controldata.chkpnt_tli,
              old_cluster.controldata.logid, old_cluster.controldata.nxtlogseg,
!               new_cluster.pgdata, log_opts.filename);
      check_ok();
  }

--- 348,360 ----
      exec_prog(true, SYSTEMQUOTE "\"%s/pg_resetxlog\" -l %u,%u,%u \"%s\" >> \"%s\" 2>&1" SYSTEMQUOTE,
                new_cluster.bindir, old_cluster.controldata.chkpnt_tli,
              old_cluster.controldata.logid, old_cluster.controldata.nxtlogseg,
!               new_cluster.pgdata,
! #ifndef WIN32
!               log_opts.filename
! #else
!               DEVNULL
! #endif
!               );
      check_ok();
  }

diff --git a/contrib/pg_upgrade/server.c b/contrib/pg_upgrade/server.c
new file mode 100644
index 58c1234..e86540b
*** a/contrib/pg_upgrade/server.c
--- b/contrib/pg_upgrade/server.c
*************** start_postmaster(ClusterInfo *cluster)
*** 184,190 ****
               (cluster->controldata.cat_ver >=
                BINARY_UPGRADE_SERVER_FLAG_CAT_VER) ? "-b" :
               "-c autovacuum=off -c autovacuum_freeze_max_age=2000000000",
!              log_opts.filename);

      /*
       * Don't throw an error right away, let connecting throw the error because
--- 184,190 ----
               (cluster->controldata.cat_ver >=
                BINARY_UPGRADE_SERVER_FLAG_CAT_VER) ? "-b" :
               "-c autovacuum=off -c autovacuum_freeze_max_age=2000000000",
!              output_filename);

      /*
       * Don't throw an error right away, let connecting throw the error because
diff --git a/contrib/pg_upgrade/check.c b/contrib/pg_upgrade/check.c
new file mode 100644
index fa4ef8d..528b674
*** a/contrib/pg_upgrade/check.c
--- b/contrib/pg_upgrade/check.c
*************** issue_warnings(char *sequence_script_fil
*** 170,176 ****
                        "--no-psqlrc --port %d --username \"%s\" "
                        "-f \"%s\" --dbname template1 >> \"%s\"" SYSTEMQUOTE,
                        new_cluster.bindir, new_cluster.port, os_info.user,
!                       sequence_script_file_name, log_opts.filename);
              unlink(sequence_script_file_name);
              check_ok();
          }
--- 170,176 ----
                        "--no-psqlrc --port %d --username \"%s\" "
                        "-f \"%s\" --dbname template1 >> \"%s\"" SYSTEMQUOTE,
                        new_cluster.bindir, new_cluster.port, os_info.user,
!                       sequence_script_file_name, log_opts.filename2);
              unlink(sequence_script_file_name);
              check_ok();
          }
diff --git a/contrib/pg_upgrade/option.c b/contrib/pg_upgrade/option.c
new file mode 100644
index 1793bb3..32bd3b8
*** a/contrib/pg_upgrade/option.c
--- b/contrib/pg_upgrade/option.c
*************** parseCommandLine(int argc, char *argv[])
*** 192,199 ****
              pg_log(PG_FATAL, "cannot write to log file %s\n", log_opts.filename);
      }
      else
!         log_opts.filename = strdup(DEVNULL);

      /* if no debug file name, output to the terminal */
      if (log_opts.debug && !log_opts.debug_fd)
      {
--- 192,206 ----
              pg_log(PG_FATAL, "cannot write to log file %s\n", log_opts.filename);
      }
      else
!         log_opts.filename = pg_strdup(DEVNULL);

+     /* WIN32 files do not accept writes from multiple processes */
+ #ifndef WIN32
+     log_opts.filename2 = pg_strdup(log_opts.filename);
+ #else
+     log_opts.filename2 = pg_strdup(DEVNULL);
+ #endif
+
      /* if no debug file name, output to the terminal */
      if (log_opts.debug && !log_opts.debug_fd)
      {
diff --git a/contrib/pg_upgrade/pg_upgrade.c b/contrib/pg_upgrade/pg_upgrade.c
new file mode 100644
index efa5c0f..4912f77
*** a/contrib/pg_upgrade/pg_upgrade.c
--- b/contrib/pg_upgrade/pg_upgrade.c
*************** prepare_new_cluster(void)
*** 193,200 ****
      prep_status("Analyzing all rows in the new cluster");
      exec_prog(true,
                SYSTEMQUOTE "\"%s/vacuumdb\" --port %d --username \"%s\" "
!               "--all --analyze >> %s 2>&1" SYSTEMQUOTE,
!       new_cluster.bindir, new_cluster.port, os_info.user, log_opts.filename);
      check_ok();

      /*
--- 193,200 ----
      prep_status("Analyzing all rows in the new cluster");
      exec_prog(true,
                SYSTEMQUOTE "\"%s/vacuumdb\" --port %d --username \"%s\" "
!               "--all --analyze >> \"%s\" 2>&1" SYSTEMQUOTE,
!       new_cluster.bindir, new_cluster.port, os_info.user, log_opts.filename2);
      check_ok();

      /*
*************** prepare_new_cluster(void)
*** 206,213 ****
      prep_status("Freezing all rows on the new cluster");
      exec_prog(true,
                SYSTEMQUOTE "\"%s/vacuumdb\" --port %d --username \"%s\" "
!               "--all --freeze >> %s 2>&1" SYSTEMQUOTE,
!       new_cluster.bindir, new_cluster.port, os_info.user, log_opts.filename);
      check_ok();

      get_pg_database_relfilenode(&new_cluster);
--- 206,213 ----
      prep_status("Freezing all rows on the new cluster");
      exec_prog(true,
                SYSTEMQUOTE "\"%s/vacuumdb\" --port %d --username \"%s\" "
!               "--all --freeze >> \"%s\" 2>&1" SYSTEMQUOTE,
!       new_cluster.bindir, new_cluster.port, os_info.user, log_opts.filename2);
      check_ok();

      get_pg_database_relfilenode(&new_cluster);
*************** prepare_new_databases(void)
*** 245,251 ****
                "--no-psqlrc --port %d --username \"%s\" "
                "-f \"%s/%s\" --dbname template1 >> \"%s\"" SYSTEMQUOTE,
                new_cluster.bindir, new_cluster.port, os_info.user, os_info.cwd,
!               GLOBALS_DUMP_FILE, log_opts.filename);
      check_ok();

      /* we load this to get a current list of databases */
--- 245,251 ----
                "--no-psqlrc --port %d --username \"%s\" "
                "-f \"%s/%s\" --dbname template1 >> \"%s\"" SYSTEMQUOTE,
                new_cluster.bindir, new_cluster.port, os_info.user, os_info.cwd,
!               GLOBALS_DUMP_FILE, log_opts.filename2);
      check_ok();

      /* we load this to get a current list of databases */
*************** create_new_objects(void)
*** 276,282 ****
                "--no-psqlrc --port %d --username \"%s\" "
                "-f \"%s/%s\" --dbname template1 >> \"%s\"" SYSTEMQUOTE,
                new_cluster.bindir, new_cluster.port, os_info.user, os_info.cwd,
!               DB_DUMP_FILE, log_opts.filename);
      check_ok();

      /* regenerate now that we have objects in the databases */
--- 276,282 ----
                "--no-psqlrc --port %d --username \"%s\" "
                "-f \"%s/%s\" --dbname template1 >> \"%s\"" SYSTEMQUOTE,
                new_cluster.bindir, new_cluster.port, os_info.user, os_info.cwd,
!               DB_DUMP_FILE, log_opts.filename2);
      check_ok();

      /* regenerate now that we have objects in the databases */
*************** copy_clog_xlog_xid(void)
*** 324,330 ****
      exec_prog(true, SYSTEMQUOTE "\"%s/pg_resetxlog\" -l %u,%u,%u \"%s\" >> \"%s\" 2>&1" SYSTEMQUOTE,
                new_cluster.bindir, old_cluster.controldata.chkpnt_tli,
              old_cluster.controldata.logid, old_cluster.controldata.nxtlogseg,
!               new_cluster.pgdata, log_opts.filename);
      check_ok();
  }

--- 324,330 ----
      exec_prog(true, SYSTEMQUOTE "\"%s/pg_resetxlog\" -l %u,%u,%u \"%s\" >> \"%s\" 2>&1" SYSTEMQUOTE,
                new_cluster.bindir, old_cluster.controldata.chkpnt_tli,
              old_cluster.controldata.logid, old_cluster.controldata.nxtlogseg,
!               new_cluster.pgdata, log_opts.filename2);
      check_ok();
  }

diff --git a/contrib/pg_upgrade/pg_upgrade.h b/contrib/pg_upgrade/pg_upgrade.h
new file mode 100644
index 4729ac3..df884bd
*** a/contrib/pg_upgrade/pg_upgrade.h
--- b/contrib/pg_upgrade/pg_upgrade.h
*************** typedef struct
*** 199,204 ****
--- 199,214 ----
  typedef struct
  {
      char       *filename;        /* name of log file (may be /dev/null) */
+     /*
+      * WIN32 files do not accept writes from multiple processes
+      *
+      * On Win32, we can't send both pg_upgrade output and command output to the
+      * same file because we get the error: "The process cannot access the file
+      * because it is being used by another process." so we have to send all
+      * other output to 'nul'.  Therefore, we set this to DEVNULL on Win32, and
+      * it equals 'filename' on all other platforms.
+      */
+     char       *filename2;
      FILE       *fd;                /* log FILE */
      bool        debug;            /* TRUE -> log more information */
      FILE       *debug_fd;        /* debug-level log FILE */
diff --git a/contrib/pg_upgrade/server.c b/contrib/pg_upgrade/server.c
new file mode 100644
index 59eaad9..17231da
*** a/contrib/pg_upgrade/server.c
--- b/contrib/pg_upgrade/server.c
*************** start_postmaster(ClusterInfo *cluster)
*** 147,165 ****
      bool        exit_hook_registered = false;
      int            pg_ctl_return = 0;

- #ifndef WIN32
-     char       *output_filename = log_opts.filename;
- #else
-
-     /*
-      * On Win32, we can't send both pg_upgrade output and pg_ctl output to the
-      * same file because we get the error: "The process cannot access the file
-      * because it is being used by another process." so we have to send all
-      * other output to 'nul'.
-      */
-     char       *output_filename = DEVNULL;
- #endif
-
      if (!exit_hook_registered)
      {
  #ifdef HAVE_ATEXIT
--- 147,152 ----
*************** start_postmaster(ClusterInfo *cluster)
*** 180,190 ****
      snprintf(cmd, sizeof(cmd),
               SYSTEMQUOTE "\"%s/pg_ctl\" -w -l \"%s\" -D \"%s\" "
               "-o \"-p %d %s\" start >> \"%s\" 2>&1" SYSTEMQUOTE,
!              cluster->bindir, output_filename, cluster->pgdata, cluster->port,
               (cluster->controldata.cat_ver >=
                BINARY_UPGRADE_SERVER_FLAG_CAT_VER) ? "-b" :
               "-c autovacuum=off -c autovacuum_freeze_max_age=2000000000",
!              log_opts.filename);

      /*
       * Don't throw an error right away, let connecting throw the error because
--- 167,177 ----
      snprintf(cmd, sizeof(cmd),
               SYSTEMQUOTE "\"%s/pg_ctl\" -w -l \"%s\" -D \"%s\" "
               "-o \"-p %d %s\" start >> \"%s\" 2>&1" SYSTEMQUOTE,
!              cluster->bindir, log_opts.filename2, cluster->pgdata, cluster->port,
               (cluster->controldata.cat_ver >=
                BINARY_UPGRADE_SERVER_FLAG_CAT_VER) ? "-b" :
               "-c autovacuum=off -c autovacuum_freeze_max_age=2000000000",
!              log_opts.filename2);

      /*
       * Don't throw an error right away, let connecting throw the error because
*************** stop_postmaster(bool fast)
*** 221,233 ****
      const char *bindir;
      const char *datadir;

- #ifndef WIN32
-     char       *output_filename = log_opts.filename;
- #else
-     /* See comment in start_postmaster() about why win32 output is ignored. */
-     char       *output_filename = DEVNULL;
- #endif
-
      if (os_info.running_cluster == &old_cluster)
      {
          bindir = old_cluster.bindir;
--- 208,213 ----
*************** stop_postmaster(bool fast)
*** 244,251 ****
      snprintf(cmd, sizeof(cmd),
               SYSTEMQUOTE "\"%s/pg_ctl\" -w -l \"%s\" -D \"%s\" %s stop >> "
               "\"%s\" 2>&1" SYSTEMQUOTE,
!              bindir, output_filename, datadir, fast ? "-m fast" : "",
!              output_filename);

      exec_prog(fast ? false : true, "%s", cmd);

--- 224,231 ----
      snprintf(cmd, sizeof(cmd),
               SYSTEMQUOTE "\"%s/pg_ctl\" -w -l \"%s\" -D \"%s\" %s stop >> "
               "\"%s\" 2>&1" SYSTEMQUOTE,
!              bindir, log_opts.filename2, datadir, fast ? "-m fast" : "",
!              log_opts.filename2);

      exec_prog(fast ? false : true, "%s", cmd);


Re: pg_upgrade and log file output on Windows

От
Bruce Momjian
Дата:
I started thinking more about this --- we already allow multiple
processes to write to a single file when running Postgres as a backend
on Windows.  I think it is these open() flags that make it possible:
               (FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE),

However, we are not going to be able to make all shell and command-line
tools use those flags, so the best solution seems to just avoid the
extra logging.  I just added a C comment to pg_upgrade to document this.

---------------------------------------------------------------------------

bruce wrote:
> 
> I have fixed the bug below with the attached patches for 9.0, 9.1, and
> 9.2.  I did a minimal patch for 9.0 and 9.1, and a more thorough patch
> for 9.2.
> 
> The use of -l/log was tested originally in pg_migrator (for 8.4) and
> reported to be working, but it turns out it only worked in 'check' mode,
> and threw an error during actual upgrade.  This bug was reported to me
> recently by EnterpriseDB testing of PG 9.0 on Windows.  The 9.2 C
> comments should make it clear that Windows doesn't allow multiple
> processes to write to the same file and  should avoid future breakage.
> 
> ---------------------------------------------------------------------------
> 
> Bruce Momjian wrote:
> > Has anyone successfully used pg_upgrade 9.0 with -l (log) on Windows?
> > 
> > I received a private email bug report that pg_upgrade 9.0 does not work
> > with the -l/log option on Windows.  The error is:
> > 
> >     Analyzing all rows in the new cluster
> >     ""c:/MinGW/msys/1.0/home/edb/inst/bin/vacuumdb" --port 55445 --username "edb" --all --analyze
> >     >> c:/MinGW/msys/1.0/home/edb/auxschedule/test.log 2>&1"
> >     The process cannot access the file because it is being used by another
> >     process.
> >
> > What has me confused is this same code exists in pg_migrator, which was
> > fixed to work with -l on Windows by Hiroshi Saito with this change:
> > 
> >         /*
> >          * On Win32, we can't send both server output and pg_ctl output
> >          * to the same file because we get the error:
> >          * "The process cannot access the file because it is being used by another process."
> >          * so we have to send pg_ctl output to 'nul'.
> >          */
> >         sprintf(cmd, SYSTEMQUOTE "\"%s/pg_ctl\" -l \"%s\" -D \"%s\" "
> >         "-o \"-p %d -c autovacuum=off -c autovacuum_freeze_max_age=2000000000\" "
> >                 "start >> \"%s\" 2>&1" SYSTEMQUOTE,
> >                  bindir, ctx->logfile, datadir, port,
> >     #ifndef WIN32
> >                  ctx->logfile);
> >     #else
> >                  DEVNULL);
> >     #endif
> > 
> > The fix was not to use the same log file and output file for pg_ctl. 
> > But as you can see, the pg_ctl and vacuumdb code is unchanged:
> > 
> >     prep_status(ctx, "Analyzing all rows in the new cluster");
> >     exec_prog(ctx, true,
> >               SYSTEMQUOTE "\"%s/vacuumdb\" --port %d --username \"%s\" "
> >               "--all --analyze >> %s 2>&1" SYSTEMQUOTE,
> >               ctx->new.bindir, ctx->new.port, ctx->user, ctx->logfile);
> > 
> > I can't figure out of there is something odd about this user's setup or
> > if there is a bug in pg_upgrade with -l on Windows.
> > 
> > -- 
> >   Bruce Momjian  <bruce@momjian.us>        http://momjian.us
> >   EnterpriseDB                             http://enterprisedb.com
> > 
> >   + It's impossible for everything to be true. +
> > 
> > -- 
> > Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
> > To make changes to your subscription:
> > http://www.postgresql.org/mailpref/pgsql-hackers
> 
> -- 
>   Bruce Momjian  <bruce@momjian.us>        http://momjian.us
>   EnterpriseDB                             http://enterprisedb.com
> 
>   + It's impossible for everything to be true. +

[ text/x-diff is unsupported, treating like TEXT/PLAIN ]

> diff --git a/contrib/pg_upgrade/pg_upgrade.c b/contrib/pg_upgrade/pg_upgrade.c
> new file mode 100644
> index 1a515e7..37d2eed
> *** a/contrib/pg_upgrade/pg_upgrade.c
> --- b/contrib/pg_upgrade/pg_upgrade.c
> *************** prepare_new_cluster(migratorContext *ctx
> *** 161,168 ****
>       prep_status(ctx, "Analyzing all rows in the new cluster");
>       exec_prog(ctx, true,
>                 SYSTEMQUOTE "\"%s/vacuumdb\" --port %d --username \"%s\" "
> !               "--all --analyze >> %s 2>&1" SYSTEMQUOTE,
> !               ctx->new.bindir, ctx->new.port, ctx->user, ctx->logfile);
>       check_ok(ctx);
>   
>       /*
> --- 161,174 ----
>       prep_status(ctx, "Analyzing all rows in the new cluster");
>       exec_prog(ctx, true,
>                 SYSTEMQUOTE "\"%s/vacuumdb\" --port %d --username \"%s\" "
> !               "--all --analyze >> \"%s\" 2>&1" SYSTEMQUOTE,
> !               ctx->new.bindir, ctx->new.port, ctx->user,
> ! #ifndef WIN32
> !               ctx->logfile
> ! #else
> !               DEVNULL
> ! #endif
> !               );
>       check_ok(ctx);
>   
>       /*
> *************** prepare_new_cluster(migratorContext *ctx
> *** 174,181 ****
>       prep_status(ctx, "Freezing all rows on the new cluster");
>       exec_prog(ctx, true,
>                 SYSTEMQUOTE "\"%s/vacuumdb\" --port %d --username \"%s\" "
> !               "--all --freeze >> %s 2>&1" SYSTEMQUOTE,
> !               ctx->new.bindir, ctx->new.port, ctx->user, ctx->logfile);
>       check_ok(ctx);
>   
>       get_pg_database_relfilenode(ctx, CLUSTER_NEW);
> --- 180,193 ----
>       prep_status(ctx, "Freezing all rows on the new cluster");
>       exec_prog(ctx, true,
>                 SYSTEMQUOTE "\"%s/vacuumdb\" --port %d --username \"%s\" "
> !               "--all --freeze >> \"%s\" 2>&1" SYSTEMQUOTE,
> !               ctx->new.bindir, ctx->new.port, ctx->user,
> ! #ifndef WIN32
> !               ctx->logfile
> ! #else
> !               DEVNULL
> ! #endif
> !               );
>       check_ok(ctx);
>   
>       get_pg_database_relfilenode(ctx, CLUSTER_NEW);
> *************** prepare_new_databases(migratorContext *c
> *** 207,213 ****
>                 "--no-psqlrc --port %d --username \"%s\" "
>                 "-f \"%s/%s\" --dbname template1 >> \"%s\"" SYSTEMQUOTE,
>                 ctx->new.bindir, ctx->new.port, ctx->user, ctx->cwd,
> !               GLOBALS_DUMP_FILE, ctx->logfile);
>       check_ok(ctx);
>   
>       get_db_and_rel_infos(ctx, &ctx->new.dbarr, CLUSTER_NEW);
> --- 219,231 ----
>                 "--no-psqlrc --port %d --username \"%s\" "
>                 "-f \"%s/%s\" --dbname template1 >> \"%s\"" SYSTEMQUOTE,
>                 ctx->new.bindir, ctx->new.port, ctx->user, ctx->cwd,
> !               GLOBALS_DUMP_FILE,
> ! #ifndef WIN32
> !               ctx->logfile
> ! #else
> !               DEVNULL
> ! #endif
> !               );
>       check_ok(ctx);
>   
>       get_db_and_rel_infos(ctx, &ctx->new.dbarr, CLUSTER_NEW);
> *************** create_new_objects(migratorContext *ctx)
> *** 230,236 ****
>                 "--no-psqlrc --port %d --username \"%s\" "
>                 "-f \"%s/%s\" --dbname template1 >> \"%s\"" SYSTEMQUOTE,
>                 ctx->new.bindir, ctx->new.port, ctx->user, ctx->cwd,
> !               DB_DUMP_FILE, ctx->logfile);
>       check_ok(ctx);
>   
>       /* regenerate now that we have db schemas */
> --- 248,260 ----
>                 "--no-psqlrc --port %d --username \"%s\" "
>                 "-f \"%s/%s\" --dbname template1 >> \"%s\"" SYSTEMQUOTE,
>                 ctx->new.bindir, ctx->new.port, ctx->user, ctx->cwd,
> !               DB_DUMP_FILE,
> ! #ifndef WIN32
> !               ctx->logfile
> ! #else
> !               DEVNULL
> ! #endif
> !               );
>       check_ok(ctx);
>   
>       /* regenerate now that we have db schemas */
> *************** copy_clog_xlog_xid(migratorContext *ctx)
> *** 282,288 ****
>       exec_prog(ctx, true, SYSTEMQUOTE "\"%s/pg_resetxlog\" -l %u,%u,%u \"%s\" >> \"%s\" 2>&1" SYSTEMQUOTE,
>                 ctx->new.bindir, ctx->old.controldata.chkpnt_tli,
>                 ctx->old.controldata.logid, ctx->old.controldata.nxtlogseg,
> !               ctx->new.pgdata, ctx->logfile);
>       check_ok(ctx);
>   }
>   
> --- 306,318 ----
>       exec_prog(ctx, true, SYSTEMQUOTE "\"%s/pg_resetxlog\" -l %u,%u,%u \"%s\" >> \"%s\" 2>&1" SYSTEMQUOTE,
>                 ctx->new.bindir, ctx->old.controldata.chkpnt_tli,
>                 ctx->old.controldata.logid, ctx->old.controldata.nxtlogseg,
> !               ctx->new.pgdata,
> ! #ifndef WIN32
> !               ctx->logfile
> ! #else
> !               DEVNULL
> ! #endif
> !               );
>       check_ok(ctx);
>   }
>   

[ text/x-diff is unsupported, treating like TEXT/PLAIN ]

> diff --git a/contrib/pg_upgrade/pg_upgrade.c b/contrib/pg_upgrade/pg_upgrade.c
> new file mode 100644
> index e329dc3..abd3d5f
> *** a/contrib/pg_upgrade/pg_upgrade.c
> --- b/contrib/pg_upgrade/pg_upgrade.c
> *************** prepare_new_cluster(void)
> *** 193,200 ****
>       prep_status("Analyzing all rows in the new cluster");
>       exec_prog(true,
>                 SYSTEMQUOTE "\"%s/vacuumdb\" --port %d --username \"%s\" "
> !               "--all --analyze >> %s 2>&1" SYSTEMQUOTE,
> !       new_cluster.bindir, new_cluster.port, os_info.user, log_opts.filename);
>       check_ok();
>   
>       /*
> --- 193,206 ----
>       prep_status("Analyzing all rows in the new cluster");
>       exec_prog(true,
>                 SYSTEMQUOTE "\"%s/vacuumdb\" --port %d --username \"%s\" "
> !               "--all --analyze >> \"%s\" 2>&1" SYSTEMQUOTE,
> !       new_cluster.bindir, new_cluster.port, os_info.user,
> ! #ifndef WIN32
> !       log_opts.filename
> ! #else
> !       DEVNULL
> ! #endif
> !       );
>       check_ok();
>   
>       /*
> *************** prepare_new_cluster(void)
> *** 206,213 ****
>       prep_status("Freezing all rows on the new cluster");
>       exec_prog(true,
>                 SYSTEMQUOTE "\"%s/vacuumdb\" --port %d --username \"%s\" "
> !               "--all --freeze >> %s 2>&1" SYSTEMQUOTE,
> !       new_cluster.bindir, new_cluster.port, os_info.user, log_opts.filename);
>       check_ok();
>   
>       get_pg_database_relfilenode(&new_cluster);
> --- 212,225 ----
>       prep_status("Freezing all rows on the new cluster");
>       exec_prog(true,
>                 SYSTEMQUOTE "\"%s/vacuumdb\" --port %d --username \"%s\" "
> !               "--all --freeze >> \"%s\" 2>&1" SYSTEMQUOTE,
> !       new_cluster.bindir, new_cluster.port, os_info.user,
> ! #ifndef WIN32
> !       log_opts.filename
> ! #else
> !       DEVNULL
> ! #endif
> !       );
>       check_ok();
>   
>       get_pg_database_relfilenode(&new_cluster);
> *************** prepare_new_databases(void)
> *** 245,251 ****
>                 "--no-psqlrc --port %d --username \"%s\" "
>                 "-f \"%s/%s\" --dbname template1 >> \"%s\"" SYSTEMQUOTE,
>                 new_cluster.bindir, new_cluster.port, os_info.user, os_info.cwd,
> !               GLOBALS_DUMP_FILE, log_opts.filename);
>       check_ok();
>   
>       /* we load this to get a current list of databases */
> --- 257,269 ----
>                 "--no-psqlrc --port %d --username \"%s\" "
>                 "-f \"%s/%s\" --dbname template1 >> \"%s\"" SYSTEMQUOTE,
>                 new_cluster.bindir, new_cluster.port, os_info.user, os_info.cwd,
> !               GLOBALS_DUMP_FILE,
> ! #ifndef WIN32
> !               log_opts.filename
> ! #else
> !               DEVNULL
> ! #endif
> !               );
>       check_ok();
>   
>       /* we load this to get a current list of databases */
> *************** create_new_objects(void)
> *** 276,282 ****
>                 "--no-psqlrc --port %d --username \"%s\" "
>                 "-f \"%s/%s\" --dbname template1 >> \"%s\"" SYSTEMQUOTE,
>                 new_cluster.bindir, new_cluster.port, os_info.user, os_info.cwd,
> !               DB_DUMP_FILE, log_opts.filename);
>       check_ok();
>   
>       /* regenerate now that we have objects in the databases */
> --- 294,306 ----
>                 "--no-psqlrc --port %d --username \"%s\" "
>                 "-f \"%s/%s\" --dbname template1 >> \"%s\"" SYSTEMQUOTE,
>                 new_cluster.bindir, new_cluster.port, os_info.user, os_info.cwd,
> !               DB_DUMP_FILE,
> ! #ifndef WIN32
> !               log_opts.filename
> ! #else
> !               DEVNULL
> ! #endif
> !               );
>       check_ok();
>   
>       /* regenerate now that we have objects in the databases */
> *************** copy_clog_xlog_xid(void)
> *** 324,330 ****
>       exec_prog(true, SYSTEMQUOTE "\"%s/pg_resetxlog\" -l %u,%u,%u \"%s\" >> \"%s\" 2>&1" SYSTEMQUOTE,
>                 new_cluster.bindir, old_cluster.controldata.chkpnt_tli,
>               old_cluster.controldata.logid, old_cluster.controldata.nxtlogseg,
> !               new_cluster.pgdata, log_opts.filename);
>       check_ok();
>   }
>   
> --- 348,360 ----
>       exec_prog(true, SYSTEMQUOTE "\"%s/pg_resetxlog\" -l %u,%u,%u \"%s\" >> \"%s\" 2>&1" SYSTEMQUOTE,
>                 new_cluster.bindir, old_cluster.controldata.chkpnt_tli,
>               old_cluster.controldata.logid, old_cluster.controldata.nxtlogseg,
> !               new_cluster.pgdata,
> ! #ifndef WIN32
> !               log_opts.filename
> ! #else
> !               DEVNULL
> ! #endif
> !               );
>       check_ok();
>   }
>   
> diff --git a/contrib/pg_upgrade/server.c b/contrib/pg_upgrade/server.c
> new file mode 100644
> index 58c1234..e86540b
> *** a/contrib/pg_upgrade/server.c
> --- b/contrib/pg_upgrade/server.c
> *************** start_postmaster(ClusterInfo *cluster)
> *** 184,190 ****
>                (cluster->controldata.cat_ver >=
>                 BINARY_UPGRADE_SERVER_FLAG_CAT_VER) ? "-b" :
>                "-c autovacuum=off -c autovacuum_freeze_max_age=2000000000",
> !              log_opts.filename);
>   
>       /*
>        * Don't throw an error right away, let connecting throw the error because
> --- 184,190 ----
>                (cluster->controldata.cat_ver >=
>                 BINARY_UPGRADE_SERVER_FLAG_CAT_VER) ? "-b" :
>                "-c autovacuum=off -c autovacuum_freeze_max_age=2000000000",
> !              output_filename);
>   
>       /*
>        * Don't throw an error right away, let connecting throw the error because

[ text/x-diff is unsupported, treating like TEXT/PLAIN ]

> diff --git a/contrib/pg_upgrade/check.c b/contrib/pg_upgrade/check.c
> new file mode 100644
> index fa4ef8d..528b674
> *** a/contrib/pg_upgrade/check.c
> --- b/contrib/pg_upgrade/check.c
> *************** issue_warnings(char *sequence_script_fil
> *** 170,176 ****
>                         "--no-psqlrc --port %d --username \"%s\" "
>                         "-f \"%s\" --dbname template1 >> \"%s\"" SYSTEMQUOTE,
>                         new_cluster.bindir, new_cluster.port, os_info.user,
> !                       sequence_script_file_name, log_opts.filename);
>               unlink(sequence_script_file_name);
>               check_ok();
>           }
> --- 170,176 ----
>                         "--no-psqlrc --port %d --username \"%s\" "
>                         "-f \"%s\" --dbname template1 >> \"%s\"" SYSTEMQUOTE,
>                         new_cluster.bindir, new_cluster.port, os_info.user,
> !                       sequence_script_file_name, log_opts.filename2);
>               unlink(sequence_script_file_name);
>               check_ok();
>           }
> diff --git a/contrib/pg_upgrade/option.c b/contrib/pg_upgrade/option.c
> new file mode 100644
> index 1793bb3..32bd3b8
> *** a/contrib/pg_upgrade/option.c
> --- b/contrib/pg_upgrade/option.c
> *************** parseCommandLine(int argc, char *argv[])
> *** 192,199 ****
>               pg_log(PG_FATAL, "cannot write to log file %s\n", log_opts.filename);
>       }
>       else
> !         log_opts.filename = strdup(DEVNULL);
>   
>       /* if no debug file name, output to the terminal */
>       if (log_opts.debug && !log_opts.debug_fd)
>       {
> --- 192,206 ----
>               pg_log(PG_FATAL, "cannot write to log file %s\n", log_opts.filename);
>       }
>       else
> !         log_opts.filename = pg_strdup(DEVNULL);
>   
> +     /* WIN32 files do not accept writes from multiple processes */
> + #ifndef WIN32
> +     log_opts.filename2 = pg_strdup(log_opts.filename);
> + #else
> +     log_opts.filename2 = pg_strdup(DEVNULL);
> + #endif
> +         
>       /* if no debug file name, output to the terminal */
>       if (log_opts.debug && !log_opts.debug_fd)
>       {
> diff --git a/contrib/pg_upgrade/pg_upgrade.c b/contrib/pg_upgrade/pg_upgrade.c
> new file mode 100644
> index efa5c0f..4912f77
> *** a/contrib/pg_upgrade/pg_upgrade.c
> --- b/contrib/pg_upgrade/pg_upgrade.c
> *************** prepare_new_cluster(void)
> *** 193,200 ****
>       prep_status("Analyzing all rows in the new cluster");
>       exec_prog(true,
>                 SYSTEMQUOTE "\"%s/vacuumdb\" --port %d --username \"%s\" "
> !               "--all --analyze >> %s 2>&1" SYSTEMQUOTE,
> !       new_cluster.bindir, new_cluster.port, os_info.user, log_opts.filename);
>       check_ok();
>   
>       /*
> --- 193,200 ----
>       prep_status("Analyzing all rows in the new cluster");
>       exec_prog(true,
>                 SYSTEMQUOTE "\"%s/vacuumdb\" --port %d --username \"%s\" "
> !               "--all --analyze >> \"%s\" 2>&1" SYSTEMQUOTE,
> !       new_cluster.bindir, new_cluster.port, os_info.user, log_opts.filename2);
>       check_ok();
>   
>       /*
> *************** prepare_new_cluster(void)
> *** 206,213 ****
>       prep_status("Freezing all rows on the new cluster");
>       exec_prog(true,
>                 SYSTEMQUOTE "\"%s/vacuumdb\" --port %d --username \"%s\" "
> !               "--all --freeze >> %s 2>&1" SYSTEMQUOTE,
> !       new_cluster.bindir, new_cluster.port, os_info.user, log_opts.filename);
>       check_ok();
>   
>       get_pg_database_relfilenode(&new_cluster);
> --- 206,213 ----
>       prep_status("Freezing all rows on the new cluster");
>       exec_prog(true,
>                 SYSTEMQUOTE "\"%s/vacuumdb\" --port %d --username \"%s\" "
> !               "--all --freeze >> \"%s\" 2>&1" SYSTEMQUOTE,
> !       new_cluster.bindir, new_cluster.port, os_info.user, log_opts.filename2);
>       check_ok();
>   
>       get_pg_database_relfilenode(&new_cluster);
> *************** prepare_new_databases(void)
> *** 245,251 ****
>                 "--no-psqlrc --port %d --username \"%s\" "
>                 "-f \"%s/%s\" --dbname template1 >> \"%s\"" SYSTEMQUOTE,
>                 new_cluster.bindir, new_cluster.port, os_info.user, os_info.cwd,
> !               GLOBALS_DUMP_FILE, log_opts.filename);
>       check_ok();
>   
>       /* we load this to get a current list of databases */
> --- 245,251 ----
>                 "--no-psqlrc --port %d --username \"%s\" "
>                 "-f \"%s/%s\" --dbname template1 >> \"%s\"" SYSTEMQUOTE,
>                 new_cluster.bindir, new_cluster.port, os_info.user, os_info.cwd,
> !               GLOBALS_DUMP_FILE, log_opts.filename2);
>       check_ok();
>   
>       /* we load this to get a current list of databases */
> *************** create_new_objects(void)
> *** 276,282 ****
>                 "--no-psqlrc --port %d --username \"%s\" "
>                 "-f \"%s/%s\" --dbname template1 >> \"%s\"" SYSTEMQUOTE,
>                 new_cluster.bindir, new_cluster.port, os_info.user, os_info.cwd,
> !               DB_DUMP_FILE, log_opts.filename);
>       check_ok();
>   
>       /* regenerate now that we have objects in the databases */
> --- 276,282 ----
>                 "--no-psqlrc --port %d --username \"%s\" "
>                 "-f \"%s/%s\" --dbname template1 >> \"%s\"" SYSTEMQUOTE,
>                 new_cluster.bindir, new_cluster.port, os_info.user, os_info.cwd,
> !               DB_DUMP_FILE, log_opts.filename2);
>       check_ok();
>   
>       /* regenerate now that we have objects in the databases */
> *************** copy_clog_xlog_xid(void)
> *** 324,330 ****
>       exec_prog(true, SYSTEMQUOTE "\"%s/pg_resetxlog\" -l %u,%u,%u \"%s\" >> \"%s\" 2>&1" SYSTEMQUOTE,
>                 new_cluster.bindir, old_cluster.controldata.chkpnt_tli,
>               old_cluster.controldata.logid, old_cluster.controldata.nxtlogseg,
> !               new_cluster.pgdata, log_opts.filename);
>       check_ok();
>   }
>   
> --- 324,330 ----
>       exec_prog(true, SYSTEMQUOTE "\"%s/pg_resetxlog\" -l %u,%u,%u \"%s\" >> \"%s\" 2>&1" SYSTEMQUOTE,
>                 new_cluster.bindir, old_cluster.controldata.chkpnt_tli,
>               old_cluster.controldata.logid, old_cluster.controldata.nxtlogseg,
> !               new_cluster.pgdata, log_opts.filename2);
>       check_ok();
>   }
>   
> diff --git a/contrib/pg_upgrade/pg_upgrade.h b/contrib/pg_upgrade/pg_upgrade.h
> new file mode 100644
> index 4729ac3..df884bd
> *** a/contrib/pg_upgrade/pg_upgrade.h
> --- b/contrib/pg_upgrade/pg_upgrade.h
> *************** typedef struct
> *** 199,204 ****
> --- 199,214 ----
>   typedef struct
>   {
>       char       *filename;        /* name of log file (may be /dev/null) */
> +     /*
> +      * WIN32 files do not accept writes from multiple processes
> +      *
> +      * On Win32, we can't send both pg_upgrade output and command output to the
> +      * same file because we get the error: "The process cannot access the file
> +      * because it is being used by another process." so we have to send all
> +      * other output to 'nul'.  Therefore, we set this to DEVNULL on Win32, and
> +      * it equals 'filename' on all other platforms.
> +      */
> +     char       *filename2;
>       FILE       *fd;                /* log FILE */
>       bool        debug;            /* TRUE -> log more information */
>       FILE       *debug_fd;        /* debug-level log FILE */
> diff --git a/contrib/pg_upgrade/server.c b/contrib/pg_upgrade/server.c
> new file mode 100644
> index 59eaad9..17231da
> *** a/contrib/pg_upgrade/server.c
> --- b/contrib/pg_upgrade/server.c
> *************** start_postmaster(ClusterInfo *cluster)
> *** 147,165 ****
>       bool        exit_hook_registered = false;
>       int            pg_ctl_return = 0;
>   
> - #ifndef WIN32
> -     char       *output_filename = log_opts.filename;
> - #else
> - 
> -     /*
> -      * On Win32, we can't send both pg_upgrade output and pg_ctl output to the
> -      * same file because we get the error: "The process cannot access the file
> -      * because it is being used by another process." so we have to send all
> -      * other output to 'nul'.
> -      */
> -     char       *output_filename = DEVNULL;
> - #endif
> - 
>       if (!exit_hook_registered)
>       {
>   #ifdef HAVE_ATEXIT
> --- 147,152 ----
> *************** start_postmaster(ClusterInfo *cluster)
> *** 180,190 ****
>       snprintf(cmd, sizeof(cmd),
>                SYSTEMQUOTE "\"%s/pg_ctl\" -w -l \"%s\" -D \"%s\" "
>                "-o \"-p %d %s\" start >> \"%s\" 2>&1" SYSTEMQUOTE,
> !              cluster->bindir, output_filename, cluster->pgdata, cluster->port,
>                (cluster->controldata.cat_ver >=
>                 BINARY_UPGRADE_SERVER_FLAG_CAT_VER) ? "-b" :
>                "-c autovacuum=off -c autovacuum_freeze_max_age=2000000000",
> !              log_opts.filename);
>   
>       /*
>        * Don't throw an error right away, let connecting throw the error because
> --- 167,177 ----
>       snprintf(cmd, sizeof(cmd),
>                SYSTEMQUOTE "\"%s/pg_ctl\" -w -l \"%s\" -D \"%s\" "
>                "-o \"-p %d %s\" start >> \"%s\" 2>&1" SYSTEMQUOTE,
> !              cluster->bindir, log_opts.filename2, cluster->pgdata, cluster->port,
>                (cluster->controldata.cat_ver >=
>                 BINARY_UPGRADE_SERVER_FLAG_CAT_VER) ? "-b" :
>                "-c autovacuum=off -c autovacuum_freeze_max_age=2000000000",
> !              log_opts.filename2);
>   
>       /*
>        * Don't throw an error right away, let connecting throw the error because
> *************** stop_postmaster(bool fast)
> *** 221,233 ****
>       const char *bindir;
>       const char *datadir;
>   
> - #ifndef WIN32
> -     char       *output_filename = log_opts.filename;
> - #else
> -     /* See comment in start_postmaster() about why win32 output is ignored. */
> -     char       *output_filename = DEVNULL;
> - #endif
> - 
>       if (os_info.running_cluster == &old_cluster)
>       {
>           bindir = old_cluster.bindir;
> --- 208,213 ----
> *************** stop_postmaster(bool fast)
> *** 244,251 ****
>       snprintf(cmd, sizeof(cmd),
>                SYSTEMQUOTE "\"%s/pg_ctl\" -w -l \"%s\" -D \"%s\" %s stop >> "
>                "\"%s\" 2>&1" SYSTEMQUOTE,
> !              bindir, output_filename, datadir, fast ? "-m fast" : "",
> !              output_filename);
>   
>       exec_prog(fast ? false : true, "%s", cmd);
>   
> --- 224,231 ----
>       snprintf(cmd, sizeof(cmd),
>                SYSTEMQUOTE "\"%s/pg_ctl\" -w -l \"%s\" -D \"%s\" %s stop >> "
>                "\"%s\" 2>&1" SYSTEMQUOTE,
> !              bindir, log_opts.filename2, datadir, fast ? "-m fast" : "",
> !              log_opts.filename2);
>   
>       exec_prog(fast ? false : true, "%s", cmd);
>   

--  Bruce Momjian  <bruce@momjian.us>        http://momjian.us EnterpriseDB
http://enterprisedb.com
 + It's impossible for everything to be true. +