Skip to content

Commit a967613

Browse files
committed
Windows: Make pg_ctl reliably detect service status
pg_ctl is using isatty() to verify whether the process is running in a terminal, and if not it sends its output to Windows' Event Log ... which does the wrong thing when the output has been redirected to a pipe, as reported in bug #13592. To fix, make pg_ctl use the code we already have to detect service-ness: in the master branch, move src/backend/port/win32/security.c to src/port (with suitable tweaks so that it runs properly in backend and frontend environments); pg_ctl already has access to pgport so it Just Works. In older branches, that's likely to cause trouble, so instead duplicate the required code in pg_ctl.c. Author: Michael Paquier Bug report and diagnosis: Egon Kocjan Backpatch: all supported branches
1 parent dad0899 commit a967613

File tree

5 files changed

+63
-28
lines changed

5 files changed

+63
-28
lines changed

src/backend/port/win32/Makefile

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ subdir = src/backend/port/win32
1212
top_builddir = ../../../..
1313
include $(top_builddir)/src/Makefile.global
1414

15-
OBJS = timer.o socket.o signal.o security.o mingwcompat.o
15+
OBJS = timer.o socket.o signal.o mingwcompat.o
1616
ifeq ($(have_win32_dbghelp), yes)
1717
OBJS += crashdump.o
1818
endif

src/bin/pg_ctl/pg_ctl.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,7 @@ write_stderr(const char *fmt,...)
216216
* On Win32, we print to stderr if running on a console, or write to
217217
* eventlog if running as a service
218218
*/
219-
if (!isatty(fileno(stderr))) /* Running as a service */
219+
if (!pgwin32_is_service()) /* Running as a service */
220220
{
221221
char errbuf[2048]; /* Arbitrary size? */
222222

src/include/port/win32.h

+4-3
Original file line numberDiff line numberDiff line change
@@ -382,9 +382,6 @@ int pgwin32_waitforsinglesocket(SOCKET s, int what, int timeout);
382382

383383
extern int pgwin32_noblock;
384384

385-
/* in backend/port/win32/security.c */
386-
extern int pgwin32_is_admin(void);
387-
extern int pgwin32_is_service(void);
388385
#endif
389386

390387
/* in backend/port/win32_shmem.c */
@@ -400,6 +397,10 @@ extern void _dosmaperr(unsigned long);
400397
extern int pgwin32_putenv(const char *);
401398
extern void pgwin32_unsetenv(const char *);
402399

400+
/* in port/win32security.c */
401+
extern int pgwin32_is_service(void);
402+
extern int pgwin32_is_admin(void);
403+
403404
#define putenv(x) pgwin32_putenv(x)
404405
#define unsetenv(x) pgwin32_unsetenv(x)
405406

src/backend/port/win32/security.c renamed to src/port/win32security.c

+56-22
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,47 @@
11
/*-------------------------------------------------------------------------
22
*
3-
* security.c
3+
* win32security.c
44
* Microsoft Windows Win32 Security Support Functions
55
*
66
* Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
77
*
88
* IDENTIFICATION
9-
* src/backend/port/win32/security.c
9+
* src/port/win32security.c
1010
*
1111
*-------------------------------------------------------------------------
1212
*/
1313

14+
#ifndef FRONTEND
1415
#include "postgres.h"
16+
#else
17+
#include "postgres_fe.h"
18+
#endif
1519

1620

1721
static BOOL pgwin32_get_dynamic_tokeninfo(HANDLE token,
18-
TOKEN_INFORMATION_CLASS class, char **InfoBuffer,
19-
char *errbuf, int errsize);
22+
TOKEN_INFORMATION_CLASS class,
23+
char **InfoBuffer, char *errbuf, int errsize);
24+
25+
26+
/*
27+
* Utility wrapper for frontend and backend when reporting an error
28+
* message.
29+
*/
30+
static
31+
pg_attribute_printf(1, 2)
32+
void
33+
log_error(const char *fmt,...)
34+
{
35+
va_list ap;
36+
37+
va_start(fmt, ap);
38+
#ifndef FRONTEND
39+
write_stderr(fmt, ap);
40+
#else
41+
fprintf(stderr, fmt, ap);
42+
#endif
43+
va_end(ap);
44+
}
2045

2146
/*
2247
* Returns nonzero if the current user has administrative privileges,
@@ -40,15 +65,15 @@ pgwin32_is_admin(void)
4065

4166
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_READ, &AccessToken))
4267
{
43-
write_stderr("could not open process token: error code %lu\n",
44-
GetLastError());
68+
log_error("could not open process token: error code %lu\n",
69+
GetLastError());
4570
exit(1);
4671
}
4772

4873
if (!pgwin32_get_dynamic_tokeninfo(AccessToken, TokenGroups,
4974
&InfoBuffer, errbuf, sizeof(errbuf)))
5075
{
51-
write_stderr("%s", errbuf);
76+
log_error("%s", errbuf);
5277
exit(1);
5378
}
5479

@@ -57,29 +82,33 @@ pgwin32_is_admin(void)
5782
CloseHandle(AccessToken);
5883

5984
if (!AllocateAndInitializeSid(&NtAuthority, 2,
60-
SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0,
85+
SECURITY_BUILTIN_DOMAIN_RID,
86+
DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0,
6187
0, &AdministratorsSid))
6288
{
63-
write_stderr("could not get SID for Administrators group: error code %lu\n",
64-
GetLastError());
89+
log_error("could not get SID for Administrators group: error code %lu\n",
90+
GetLastError());
6591
exit(1);
6692
}
6793

6894
if (!AllocateAndInitializeSid(&NtAuthority, 2,
69-
SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_POWER_USERS, 0, 0, 0, 0, 0,
95+
SECURITY_BUILTIN_DOMAIN_RID,
96+
DOMAIN_ALIAS_RID_POWER_USERS, 0, 0, 0, 0, 0,
7097
0, &PowerUsersSid))
7198
{
72-
write_stderr("could not get SID for PowerUsers group: error code %lu\n",
73-
GetLastError());
99+
log_error("could not get SID for PowerUsers group: error code %lu\n",
100+
GetLastError());
74101
exit(1);
75102
}
76103

77104
success = FALSE;
78105

79106
for (x = 0; x < Groups->GroupCount; x++)
80107
{
81-
if ((EqualSid(AdministratorsSid, Groups->Groups[x].Sid) && (Groups->Groups[x].Attributes & SE_GROUP_ENABLED)) ||
82-
(EqualSid(PowerUsersSid, Groups->Groups[x].Sid) && (Groups->Groups[x].Attributes & SE_GROUP_ENABLED)))
108+
if ((EqualSid(AdministratorsSid, Groups->Groups[x].Sid) &&
109+
(Groups->Groups[x].Attributes & SE_GROUP_ENABLED)) ||
110+
(EqualSid(PowerUsersSid, Groups->Groups[x].Sid) &&
111+
(Groups->Groups[x].Attributes & SE_GROUP_ENABLED)))
83112
{
84113
success = TRUE;
85114
break;
@@ -105,9 +134,10 @@ pgwin32_is_admin(void)
105134
* 1 = Service
106135
* -1 = Error
107136
*
108-
* Note: we can't report errors via either ereport (we're called too early)
109-
* or write_stderr (because that calls this). We are therefore reduced to
110-
* writing directly on stderr, which sucks, but we have few alternatives.
137+
* Note: we can't report errors via either ereport (we're called too early
138+
* in the backend) or write_stderr (because that calls this). We are
139+
* therefore reduced to writing directly on stderr, which sucks, but we
140+
* have few alternatives.
111141
*/
112142
int
113143
pgwin32_is_service(void)
@@ -217,29 +247,33 @@ pgwin32_get_dynamic_tokeninfo(HANDLE token, TOKEN_INFORMATION_CLASS class,
217247

218248
if (GetTokenInformation(token, class, NULL, 0, &InfoBufferSize))
219249
{
220-
snprintf(errbuf, errsize, "could not get token information: got zero size\n");
250+
snprintf(errbuf, errsize,
251+
"could not get token information: got zero size\n");
221252
return FALSE;
222253
}
223254

224255
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
225256
{
226-
snprintf(errbuf, errsize, "could not get token information: error code %lu\n",
257+
snprintf(errbuf, errsize,
258+
"could not get token information: error code %lu\n",
227259
GetLastError());
228260
return FALSE;
229261
}
230262

231263
*InfoBuffer = malloc(InfoBufferSize);
232264
if (*InfoBuffer == NULL)
233265
{
234-
snprintf(errbuf, errsize, "could not allocate %d bytes for token information\n",
266+
snprintf(errbuf, errsize,
267+
"could not allocate %d bytes for token information\n",
235268
(int) InfoBufferSize);
236269
return FALSE;
237270
}
238271

239272
if (!GetTokenInformation(token, class, *InfoBuffer,
240273
InfoBufferSize, &InfoBufferSize))
241274
{
242-
snprintf(errbuf, errsize, "could not get token information: error code %lu\n",
275+
snprintf(errbuf, errsize,
276+
"could not get token information: error code %lu\n",
243277
GetLastError());
244278
return FALSE;
245279
}

src/tools/msvc/Mkvcbuild.pm

+1-1
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ sub mkvcbuild
9090
pgcheckdir.c pgmkdirp.c pgsleep.c pgstrcasecmp.c pqsignal.c
9191
mkdtemp.c qsort.c qsort_arg.c quotes.c system.c
9292
sprompt.c tar.c thread.c getopt.c getopt_long.c dirent.c
93-
win32env.c win32error.c win32setlocale.c);
93+
win32env.c win32error.c win32security.c win32setlocale.c);
9494

9595
push(@pgportfiles, 'rint.c') if ($vsVersion < '12.00');
9696

0 commit comments

Comments
 (0)