Here is a patch that fixes the pipes used in find_other_exec() when
authorBruce Momjian
Mon, 26 Jul 2004 01:48:00 +0000 (01:48 +0000)
committerBruce Momjian
Mon, 26 Jul 2004 01:48:00 +0000 (01:48 +0000)
running as a service on windows <= 2000. Required to make the pg_ctl
service wrapper to work at all.

Magnus Hagander

doc/src/sgml/release.sgml
src/port/exec.c

index 10360fc1e5a8eaa49f2663f834692a132f097d22..b2c0be4edab8f64264c1aa5e7dae93529277d5e7 100644 (file)
@@ -1,5 +1,5 @@
 
 
 
@@ -1271,7 +1271,7 @@ $PostgreSQL: pgsql/doc/src/sgml/release.sgml,v 1.270 2004/07/26 00:26:42 momjian
 
     
      
-      New start/end of dump markers in pg_dump (Bruce)
+      New start/stop of dump markers in pg_dump (Bruce)
      
     
 
index c8ba1227a15e93681e60fdae5dbbdb53c22692c6..d98da090c7078f39676f5d9b1a9839ef5ed5b85a 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/port/exec.c,v 1.16 2004/06/10 22:26:24 momjian Exp $
+ *   $PostgreSQL: pgsql/src/port/exec.c,v 1.17 2004/07/26 01:48:00 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -279,6 +279,128 @@ find_my_exec(const char *argv0, char *retpath)
 #endif
 }
 
+/*
+ * The runtime librarys popen() on win32 does not work when being
+ * called from a service when running on windows <= 2000, because
+ * there is no stdin/stdout/stderr.
+ *
+ * Executing a command in a pipe and reading the first line from it
+ * is all we need.
+ */
+   
+static char *pipe_read_line(char *cmd, char *line, int maxsize)
+{
+#ifndef WIN32
+   FILE *pgver;
+
+   /* flush output buffers in case popen does not... */
+   fflush(stdout);
+   fflush(stderr);
+
+   if ((pgver = popen(cmd, "r")) == NULL)
+       return NULL;
+   
+   if (fgets(line, maxsize, pgver) == NULL)
+   {
+       perror("fgets failure");
+       return NULL;
+   }
+
+   if (pclose_check(pgver))
+       return NULL;
+   
+   return line;
+#else
+   /* Win32 */
+   SECURITY_ATTRIBUTES sattr;
+   HANDLE childstdoutrd, childstdoutwr, childstdoutrddup;
+   PROCESS_INFORMATION pi;
+   STARTUPINFO si;
+   char *retval = NULL;
+
+   sattr.nLength = sizeof(SECURITY_ATTRIBUTES);
+   sattr.bInheritHandle = TRUE;
+   sattr.lpSecurityDescriptor = NULL;
+
+   if (!CreatePipe(&childstdoutrd, &childstdoutwr, &sattr, 0))
+       return NULL;
+   
+   if (!DuplicateHandle(GetCurrentProcess(),
+                        childstdoutrd,
+                        GetCurrentProcess(),
+                        &childstdoutrddup,
+                        0,
+                        FALSE,
+                        DUPLICATE_SAME_ACCESS))
+   {
+       CloseHandle(childstdoutrd);
+       CloseHandle(childstdoutwr);
+       return NULL;
+   }
+
+   CloseHandle(childstdoutrd);
+   
+   ZeroMemory(&pi,sizeof(pi));
+   ZeroMemory(&si,sizeof(si));
+   si.cb = sizeof(si);
+   si.dwFlags = STARTF_USESTDHANDLES;
+   si.hStdError = childstdoutwr;
+   si.hStdOutput = childstdoutwr;
+   si.hStdInput = INVALID_HANDLE_VALUE;
+   
+   if (CreateProcess(NULL,
+                     cmd,
+                     NULL,
+                     NULL,
+                     TRUE,
+                     0,
+                     NULL,
+                     NULL,
+                     &si,
+                     &pi))
+   {
+       DWORD bytesread = 0;
+       /* Successfully started the process */
+
+       ZeroMemory(line,maxsize);
+       
+       /* Let's see if we can read */
+       if (WaitForSingleObject(childstdoutrddup, 10000) != WAIT_OBJECT_0) 
+       {
+           /* Got timeout */
+           CloseHandle(pi.hProcess);
+           CloseHandle(pi.hThread);
+           CloseHandle(childstdoutwr);
+           CloseHandle(childstdoutrddup);
+           return NULL;
+       }
+       
+       
+       /* We try just once */
+       if (ReadFile(childstdoutrddup, line, maxsize, &bytesread, NULL) &&
+           bytesread > 0)
+       {
+           /* So we read some data */
+           retval = line;
+
+           /* We emulate fgets() behaviour. So if there is no newline
+            * at the end, we add one... */
+           if (line[strlen(line)-1] != '\n')
+               strcat(line,"\n");
+       }
+
+       CloseHandle(pi.hProcess);
+       CloseHandle(pi.hThread);
+   }
+   
+   CloseHandle(childstdoutwr);
+   CloseHandle(childstdoutrddup);
+
+   return retval;
+#endif
+}
+   
+
 
 /*
  * Find our binary directory, then make sure the "target" executable
@@ -290,14 +412,12 @@ find_other_exec(const char *argv0, const char *target,
 {
    char        cmd[MAXPGPATH];
    char        line[100];
-   FILE       *pgver;
-
+   
    if (find_my_exec(argv0, retpath) < 0)
        return -1;
 
    /* Trim off program name and keep just directory */ 
    *last_dir_separator(retpath) = '\0';
-
    snprintf(retpath + strlen(retpath), MAXPGPATH - strlen(retpath),
             "/%s%s", target, EXE);
 
@@ -306,19 +426,9 @@ find_other_exec(const char *argv0, const char *target,
    
    snprintf(cmd, sizeof(cmd), "\"%s\" -V 2>%s", retpath, DEVNULL);
 
-   /* flush output buffers in case popen does not... */
-   fflush(stdout);
-   fflush(stderr);
-
-   if ((pgver = popen(cmd, "r")) == NULL)
-       return -1;
-
-   if (fgets(line, sizeof(line), pgver) == NULL)
-       perror("fgets failure");
-
-   if (pclose_check(pgver))
+   if (!pipe_read_line(cmd, line, sizeof(line)))
        return -1;
-
+   
    if (strcmp(line, versionstr) != 0)
        return -2;