util.c: Made write_pidfile write the correct PID on MinGW/Msys
authorMarc Hoersken <info@marc-hoersken.de>
Fri, 5 Apr 2013 22:40:25 +0000 (00:40 +0200)
committerMarc Hoersken <info@marc-hoersken.de>
Fri, 5 Apr 2013 22:41:00 +0000 (00:41 +0200)
This workaround fixes an issue on MinGW/Msys regarding the Perl
testsuite scripts not being able to signal or control the server
processes. The MinGW Perl runtime only sees the Msys processes and
their corresponding PIDs, but sockfilt (and other servers) wrote the
Windows PID into their PID-files. Since this PID is useless to the
testsuite, the write_pidfile function was changed to search for the
Msys PID and write that into the PID-file.

tests/server/util.c

index 06f3ce1..8158cb2 100644 (file)
 #define EINVAL  22 /* errno.h value */
 #endif
 
+#if __MINGW32__
+#include <TlHelp32.h>
+#endif
+
 #if defined(ENABLE_IPV6) && defined(__MINGW32__)
 const struct in6_addr in6addr_any = {{ IN6ADDR_ANY_INIT }};
 #endif
@@ -248,6 +252,58 @@ int wait_ms(int timeout_ms)
   return r;
 }
 
+#ifdef __MINGW32__
+/* WORKAROUND
+ *
+ * These functions make it possible to get the Msys PID instead of the
+ * Windows PID assigned to the current process. This is done by walking up
+ * to the Msys sh.exe process that launched the shadow Windows processes.
+ *
+ * Usually an Msys process would result in following process tree:
+ *   sh.exe           <-- waiting Windows process, but running Msys process
+ *     \
+ *     <proc>.exe     <-- waiting Windows process
+ *       \
+ *       <proc>.exe   <-- running Windows process
+ *
+ * Attention: This may not be true for all Msys processes.
+ */
+static pid_t getpid_msys(void)
+{
+  PROCESSENTRY32 entry;
+  HANDLE snapshot;
+  DWORD pid;
+  BOOL walk;
+
+  pid = (DWORD)getpid();
+
+  entry.dwSize = sizeof(PROCESSENTRY32);
+  snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, pid);
+
+  if(snapshot != INVALID_HANDLE_VALUE) {
+    walk = TRUE;
+    while(walk) {
+      if(Process32First(snapshot, &entry)) {
+        do {
+          if(pid == entry.th32ProcessID) {
+            if(!strcmp(entry.szExeFile, "sh.exe")) {
+              walk = FALSE;
+              break;
+            }
+            pid = entry.th32ParentProcessID;
+            break;
+          }
+        } while (Process32Next(snapshot, &entry));
+      }
+    }
+    CloseHandle(snapshot);
+  }
+
+  return (pid_t)pid;
+}
+#define getpid() getpid_msys()
+#endif
+
 int write_pidfile(const char *filename)
 {
   FILE *pidfile;