postgres.git / summary / log / commit / refs

commit    0da33c762b85aeada111aa1371c33ac6737f8396
Author:   Tom Lane <tgl@sss.pgh.pa.us>
Date:     Tue Dec 10 18:17:08 2019 +0000

    In pg_ctl, work around ERROR_SHARING_VIOLATION on the postmaster log file.
    
    On Windows, we use CMD.EXE to redirect the postmaster's stdout/stderr
    into a log file.  CMD.EXE will open that file with non-sharing-friendly
    parameters, and the file will remain open for a short time after the
    postmaster has removed postmaster.pid.  This can result in an
    ERROR_SHARING_VIOLATION failure if we attempt to start a new postmaster
    immediately with the same log file (e.g. during "pg_ctl restart").
    This seems to explain intermittent buildfarm failures we've been seeing
    on Windows machines.
    
    To fix, just open and close the log file using our own pgwin32_open(),
    which will wait if necessary to avoid the failure.  (Perhaps someday
    we should stop using CMD.EXE, but that would be a far more complex
    patch, and it doesn't seem worth the trouble ... yet.)
    
    Back-patch to v12.  This only solves the problem when frontend fopen()
    is redirected to pgwin32_fopen(), which has only been true since commit
    0ba06e0bf.  Hence, no point in back-patching further, unless we care
    to back-patch that change too.
    
    Diagnosis and patch by Alexander Lakhin (bug #16154).
    
    Discussion: https://postgr.es/m/16154-1ccf0b537b24d5e0@postgresql.org


src/bin/pg_ctl/pg_ctl.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/bin/pg_ctl/pg_ctl.c b/src/bin/pg_ctl/pg_ctl.c index 65f9fb4c0a9..b0858411ed9 100644 --- a/src/bin/pg_ctl/pg_ctl.c +++ b/src/bin/pg_ctl/pg_ctl.c @@ -519,8 +519,29 @@ start_postmaster(void) comspec = "CMD"; if (log_file != NULL) + { + /* + * First, touch the log file. The main value of this is that if the + * file is still locked by a previous postmaster run, we'll wait until + * it comes free, instead of failing with ERROR_SHARING_VIOLATION. + * (It'd be better to open the file in a sharing-friendly mode, but we + * can't use CMD.EXE to do that, so work around it. Note that the + * previous postmaster will still have the file open for a short time + * after removing postmaster.pid.) + */ + FILE *fd = fopen(log_file, "a"); + + if (fd == NULL) + { + write_stderr(_("%s: could not create log file \"%s\": %s\n"), + progname, log_file, strerror(errno)); + exit(1); + } + fclose(fd); + snprintf(cmd, MAXPGPATH, "\"%s\" /C \"\"%s\" %s%s < \"%s\" >> \"%s\" 2>&1\"", comspec, exec_path, pgdata_opt, post_opts, DEVNULL, log_file); + } else snprintf(cmd, MAXPGPATH, "\"%s\" /C \"\"%s\" %s%s < \"%s\" 2>&1\"", comspec, exec_path, pgdata_opt, post_opts, DEVNULL); [parent: 5a20b0219e76]