Skip to content

Commit 5b2f4af

Browse files
committed
Here is a patch that fixes the pipes used in find_other_exec() when
running as a service on windows <= 2000. Required to make the pg_ctl service wrapper to work at all. Magnus Hagander
1 parent 25a1324 commit 5b2f4af

File tree

2 files changed

+128
-18
lines changed

2 files changed

+128
-18
lines changed

doc/src/sgml/release.sgml

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<!--
2-
$PostgreSQL: pgsql/doc/src/sgml/release.sgml,v 1.270 2004/07/26 00:26:42 momjian Exp $
2+
$PostgreSQL: pgsql/doc/src/sgml/release.sgml,v 1.271 2004/07/26 01:47:59 momjian Exp $
33
-->
44

55
<appendix id="release">
@@ -1271,7 +1271,7 @@ $PostgreSQL: pgsql/doc/src/sgml/release.sgml,v 1.270 2004/07/26 00:26:42 momjian
12711271

12721272
<listitem>
12731273
<para>
1274-
New start/end of dump markers in pg_dump (Bruce)
1274+
New start/stop of dump markers in pg_dump (Bruce)
12751275
</para>
12761276
</listitem>
12771277

src/port/exec.c

+126-16
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*
88
*
99
* IDENTIFICATION
10-
* $PostgreSQL: pgsql/src/port/exec.c,v 1.16 2004/06/10 22:26:24 momjian Exp $
10+
* $PostgreSQL: pgsql/src/port/exec.c,v 1.17 2004/07/26 01:48:00 momjian Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -279,6 +279,128 @@ find_my_exec(const char *argv0, char *retpath)
279279
#endif
280280
}
281281

282+
/*
283+
* The runtime librarys popen() on win32 does not work when being
284+
* called from a service when running on windows <= 2000, because
285+
* there is no stdin/stdout/stderr.
286+
*
287+
* Executing a command in a pipe and reading the first line from it
288+
* is all we need.
289+
*/
290+
291+
static char *pipe_read_line(char *cmd, char *line, int maxsize)
292+
{
293+
#ifndef WIN32
294+
FILE *pgver;
295+
296+
/* flush output buffers in case popen does not... */
297+
fflush(stdout);
298+
fflush(stderr);
299+
300+
if ((pgver = popen(cmd, "r")) == NULL)
301+
return NULL;
302+
303+
if (fgets(line, maxsize, pgver) == NULL)
304+
{
305+
perror("fgets failure");
306+
return NULL;
307+
}
308+
309+
if (pclose_check(pgver))
310+
return NULL;
311+
312+
return line;
313+
#else
314+
/* Win32 */
315+
SECURITY_ATTRIBUTES sattr;
316+
HANDLE childstdoutrd, childstdoutwr, childstdoutrddup;
317+
PROCESS_INFORMATION pi;
318+
STARTUPINFO si;
319+
char *retval = NULL;
320+
321+
sattr.nLength = sizeof(SECURITY_ATTRIBUTES);
322+
sattr.bInheritHandle = TRUE;
323+
sattr.lpSecurityDescriptor = NULL;
324+
325+
if (!CreatePipe(&childstdoutrd, &childstdoutwr, &sattr, 0))
326+
return NULL;
327+
328+
if (!DuplicateHandle(GetCurrentProcess(),
329+
childstdoutrd,
330+
GetCurrentProcess(),
331+
&childstdoutrddup,
332+
0,
333+
FALSE,
334+
DUPLICATE_SAME_ACCESS))
335+
{
336+
CloseHandle(childstdoutrd);
337+
CloseHandle(childstdoutwr);
338+
return NULL;
339+
}
340+
341+
CloseHandle(childstdoutrd);
342+
343+
ZeroMemory(&pi,sizeof(pi));
344+
ZeroMemory(&si,sizeof(si));
345+
si.cb = sizeof(si);
346+
si.dwFlags = STARTF_USESTDHANDLES;
347+
si.hStdError = childstdoutwr;
348+
si.hStdOutput = childstdoutwr;
349+
si.hStdInput = INVALID_HANDLE_VALUE;
350+
351+
if (CreateProcess(NULL,
352+
cmd,
353+
NULL,
354+
NULL,
355+
TRUE,
356+
0,
357+
NULL,
358+
NULL,
359+
&si,
360+
&pi))
361+
{
362+
DWORD bytesread = 0;
363+
/* Successfully started the process */
364+
365+
ZeroMemory(line,maxsize);
366+
367+
/* Let's see if we can read */
368+
if (WaitForSingleObject(childstdoutrddup, 10000) != WAIT_OBJECT_0)
369+
{
370+
/* Got timeout */
371+
CloseHandle(pi.hProcess);
372+
CloseHandle(pi.hThread);
373+
CloseHandle(childstdoutwr);
374+
CloseHandle(childstdoutrddup);
375+
return NULL;
376+
}
377+
378+
379+
/* We try just once */
380+
if (ReadFile(childstdoutrddup, line, maxsize, &bytesread, NULL) &&
381+
bytesread > 0)
382+
{
383+
/* So we read some data */
384+
retval = line;
385+
386+
/* We emulate fgets() behaviour. So if there is no newline
387+
* at the end, we add one... */
388+
if (line[strlen(line)-1] != '\n')
389+
strcat(line,"\n");
390+
}
391+
392+
CloseHandle(pi.hProcess);
393+
CloseHandle(pi.hThread);
394+
}
395+
396+
CloseHandle(childstdoutwr);
397+
CloseHandle(childstdoutrddup);
398+
399+
return retval;
400+
#endif
401+
}
402+
403+
282404

283405
/*
284406
* Find our binary directory, then make sure the "target" executable
@@ -290,14 +412,12 @@ find_other_exec(const char *argv0, const char *target,
290412
{
291413
char cmd[MAXPGPATH];
292414
char line[100];
293-
FILE *pgver;
294-
415+
295416
if (find_my_exec(argv0, retpath) < 0)
296417
return -1;
297418

298419
/* Trim off program name and keep just directory */
299420
*last_dir_separator(retpath) = '\0';
300-
301421
snprintf(retpath + strlen(retpath), MAXPGPATH - strlen(retpath),
302422
"/%s%s", target, EXE);
303423

@@ -306,19 +426,9 @@ find_other_exec(const char *argv0, const char *target,
306426

307427
snprintf(cmd, sizeof(cmd), "\"%s\" -V 2>%s", retpath, DEVNULL);
308428

309-
/* flush output buffers in case popen does not... */
310-
fflush(stdout);
311-
fflush(stderr);
312-
313-
if ((pgver = popen(cmd, "r")) == NULL)
314-
return -1;
315-
316-
if (fgets(line, sizeof(line), pgver) == NULL)
317-
perror("fgets failure");
318-
319-
if (pclose_check(pgver))
429+
if (!pipe_read_line(cmd, line, sizeof(line)))
320430
return -1;
321-
431+
322432
if (strcmp(line, versionstr) != 0)
323433
return -2;
324434

0 commit comments

Comments
 (0)