Commit e02ea141 authored by Tom Lane's avatar Tom Lane

Try again to work around Windows' ERROR_SHARING_VIOLATION in pg_ctl.

Commit 0da33c76 introduced an unfortunate regression in pg_ctl on
Windows: if the log file specified with -l doesn't exist yet, and
pg_ctl is running with Administrator privileges, then the log file
might get created with permissions that prevent the postmaster from
writing on it.  (It seems that whether this happens depends on whether
the log file is inside the user's home directory or not, and perhaps
on other phase-of-the-moon conditions, which may explain why we failed
to notice it sooner.)

To fix, just don't create the log file if it doesn't exist yet.  The
case where we need to wait obviously only occurs with a pre-existing
log file.

In passing, switch from using fopen() to plain open(), saving a few
cycles.

Per bug #16259 from Jonathan Katz and Heath Lord.  Back-patch to v12,
as the faulty commit was.

Alexander Lakhin

Discussion: https://postgr.es/m/16259-c5ebed32a262a8b1@postgresql.org
parent faade5d4
...@@ -521,23 +521,37 @@ start_postmaster(void) ...@@ -521,23 +521,37 @@ start_postmaster(void)
if (log_file != NULL) if (log_file != NULL)
{ {
/* /*
* First, touch the log file. The main value of this is that if the * First, open the log file if it exists. The idea is that if the
* file is still locked by a previous postmaster run, we'll wait until * file is still locked by a previous postmaster run, we'll wait until
* it comes free, instead of failing with ERROR_SHARING_VIOLATION. * 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 * (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 * 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 * previous postmaster will still have the file open for a short time
* after removing postmaster.pid.) * after removing postmaster.pid.)
*
* If the log file doesn't exist, we *must not* create it here. If we
* were launched with higher privileges than the restricted process
* will have, the log file might end up with permissions settings that
* prevent the postmaster from writing on it.
*/ */
FILE *fd = fopen(log_file, "a"); int fd = open(log_file, O_RDWR, 0);
if (fd == NULL) if (fd == -1)
{ {
write_stderr(_("%s: could not create log file \"%s\": %s\n"), /*
progname, log_file, strerror(errno)); * ENOENT is expectable since we didn't use O_CREAT. Otherwise
exit(1); * complain. We could just fall through and let CMD.EXE report
* the problem, but its error reporting is pretty miserable.
*/
if (errno != ENOENT)
{
write_stderr(_("%s: could not open log file \"%s\": %s\n"),
progname, log_file, strerror(errno));
exit(1);
}
} }
fclose(fd); else
close(fd);
snprintf(cmd, MAXPGPATH, "\"%s\" /C \"\"%s\" %s%s < \"%s\" >> \"%s\" 2>&1\"", snprintf(cmd, MAXPGPATH, "\"%s\" /C \"\"%s\" %s%s < \"%s\" >> \"%s\" 2>&1\"",
comspec, exec_path, pgdata_opt, post_opts, DEVNULL, log_file); comspec, exec_path, pgdata_opt, post_opts, DEVNULL, log_file);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment