From 43bf3a6bc658d634e073dcb4ea3580dd9053a3b1 Mon Sep 17 00:00:00 2001
From: Bruce Momjian <bruce@momjian.us>
Date: Tue, 23 Aug 2005 21:02:05 +0000
Subject: [PATCH] The attached patch updates the thread test program to run
 stand-alone on Windows. The test itself is bypassed in configure as
 discussed, and libpq has been updated appropriately to allow it to build in
 thread-safe mode.

Dave Page
---
 configure                            |  15 ++++
 configure.in                         |  15 +++-
 src/interfaces/libpq/Makefile        |  11 +--
 src/interfaces/libpq/fe-connect.c    |   6 +-
 src/interfaces/libpq/fe-exec.c       |  23 ++---
 src/interfaces/libpq/fe-misc.c       |   8 +-
 src/interfaces/libpq/fe-print.c      |  17 ++--
 src/interfaces/libpq/fe-secure.c     |  31 ++++---
 src/interfaces/libpq/libpq-int.h     |   8 +-
 src/interfaces/libpq/pthread-win32.c |   4 +-
 src/tools/thread/README              |  33 ++++++++
 src/tools/thread/thread_test.c       | 122 ++++++++++++++++++++++++---
 12 files changed, 227 insertions(+), 66 deletions(-)

diff --git a/configure b/configure
index 95db2708304..3d4284002a0 100755
--- a/configure
+++ b/configure
@@ -20908,6 +20908,8 @@ fi
 
 
 
+if test x"$template" != x"win32"
+then
 echo "$as_me:$LINENO: checking for POSIX signal interface" >&5
 echo $ECHO_N "checking for POSIX signal interface... $ECHO_C" >&6
 if test "${pgac_cv_func_posix_signals+set}" = set; then
@@ -20986,6 +20988,7 @@ echo "$as_me: error:
 " >&2;}
    { (exit 1); exit 1; }; }
 fi
+fi
 
 if test $ac_cv_func_fseeko = yes; then
 # Check whether --enable-largefile or --disable-largefile was given.
@@ -22432,6 +22435,8 @@ done
 # defined.  Cross compiling throws a warning.
 #
 if test "$enable_thread_safety_force" = yes; then
+if test x"$template" != x"win32"
+then
   { echo "$as_me:$LINENO: WARNING:
 *** Skipping thread test program.  --enable-thread-safety-force was used.
 *** Run the program in src/tools/thread on the your machine and add
@@ -22444,7 +22449,13 @@ echo "$as_me: WARNING:
 proper locking function calls to your applications to guarantee thread
 safety.
 " >&2;}
+else
+{ echo "$as_me:$LINENO: WARNING: *** Skipping thread test on Win32" >&5
+echo "$as_me: WARNING: *** Skipping thread test on Win32" >&2;}
+fi
 elif test "$enable_thread_safety" = yes; then
+if test x"$template" != x"win32"
+then
 echo "$as_me:$LINENO: checking thread safety of required library functions" >&5
 echo $ECHO_N "checking thread safety of required library functions... $ECHO_C" >&6
 
@@ -22517,6 +22528,10 @@ rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftes
 fi
 CFLAGS="$_CFLAGS"
 LIBS="$_LIBS"
+else
+{ echo "$as_me:$LINENO: WARNING: *** Skipping thread test on Win32" >&5
+echo "$as_me: WARNING: *** Skipping thread test on Win32" >&2;}
+fi
 fi
 
 # prepare build tree if outside source tree
diff --git a/configure.in b/configure.in
index c24b1cd4c1c..8b8962f9b04 100644
--- a/configure.in
+++ b/configure.in
@@ -1,5 +1,5 @@
 dnl Process this file with autoconf to produce a configure script.
-dnl $PostgreSQL: pgsql/configure.in,v 1.422 2005/08/23 20:48:44 momjian Exp $
+dnl $PostgreSQL: pgsql/configure.in,v 1.423 2005/08/23 21:01:59 momjian Exp $
 dnl
 dnl Developers, please strive to achieve this order:
 dnl
@@ -1172,6 +1172,8 @@ AC_CHECK_TYPES([int8, uint8, int64, uint64], [], [],
 AC_CHECK_TYPES(sig_atomic_t, [], [], [#include <signal.h>])
 
 
+if test x"$template" != x"win32"
+then
 PGAC_FUNC_POSIX_SIGNALS
 if test "$pgac_cv_func_posix_signals" != yes -a "$enable_thread_safety" = yes; then
   AC_MSG_ERROR([
@@ -1179,6 +1181,7 @@ if test "$pgac_cv_func_posix_signals" != yes -a "$enable_thread_safety" = yes; t
 *** operating system.
 ])
 fi
+fi
 
 if test $ac_cv_func_fseeko = yes; then
 AC_SYS_LARGEFILE
@@ -1241,13 +1244,20 @@ AC_CHECK_PROGS(SGMLSPL, sgmlspl)
 # defined.  Cross compiling throws a warning.
 #
 if test "$enable_thread_safety_force" = yes; then
+if test x"$template" != x"win32"
+then
   AC_MSG_WARN([
 *** Skipping thread test program.  --enable-thread-safety-force was used.
 *** Run the program in src/tools/thread on the your machine and add
 proper locking function calls to your applications to guarantee thread
 safety.
 ])
+else
+AC_MSG_WARN([*** Skipping thread test on Win32])
+fi
 elif test "$enable_thread_safety" = yes; then
+if test x"$template" != x"win32"
+then
 AC_MSG_CHECKING([thread safety of required library functions])
 
 _CFLAGS="$CFLAGS"
@@ -1273,6 +1283,9 @@ AC_TRY_RUN([#include "$srcdir/src/tools/thread/thread_test.c"],
 ])])
 CFLAGS="$_CFLAGS"
 LIBS="$_LIBS"
+else
+AC_MSG_WARN([*** Skipping thread test on Win32])
+fi
 fi
 
 # prepare build tree if outside source tree
diff --git a/src/interfaces/libpq/Makefile b/src/interfaces/libpq/Makefile
index f496d595ecb..9a61803cce8 100644
--- a/src/interfaces/libpq/Makefile
+++ b/src/interfaces/libpq/Makefile
@@ -5,7 +5,7 @@
 # Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
 # Portions Copyright (c) 1994, Regents of the University of California
 #
-# $PostgreSQL: pgsql/src/interfaces/libpq/Makefile,v 1.136 2005/08/23 20:48:46 momjian Exp $
+# $PostgreSQL: pgsql/src/interfaces/libpq/Makefile,v 1.137 2005/08/23 21:02:03 momjian Exp $
 #
 #-------------------------------------------------------------------------
 
@@ -43,9 +43,7 @@ libpqrc.o: libpq.rc
 	windres -i libpq.rc -o libpqrc.o
 
 ifeq ($(enable_thread_safety), yes)
-# This doesn't work yet because configure test fails.  2004-06-19
 OBJS += pthread-win32.o
-PTHREAD_H_WIN32 = pthread.h
 endif
 endif
 
@@ -59,7 +57,7 @@ SHLIB_LINK += -lshfolder -lwsock32 -lws2_32 $(filter -leay32 -lssleay32 -lcomerr
 endif
 
 
-all: $(PTHREAD_H_WIN32) def-files $(srcdir)/libpq.rc all-lib
+all: def-files $(srcdir)/libpq.rc all-lib
 
 # Shared library stuff
 include $(top_srcdir)/src/Makefile.shlib
@@ -122,11 +120,6 @@ $(srcdir)/blibpqdll.def: exports.txt
 $(srcdir)/libpq.rc: libpq.rc.in $(top_builddir)/src/Makefile.global
 	sed -e 's/\(VERSION.*\),0 *$$/\1,'`date '+%y%j' | sed 's/^0*//'`'/' < $< > $@
 
-ifneq ($(PTHREAD_H_WIN32), "")
-pthread.h: $(top_srcdir)/src/interfaces/libpq/pthread.h.win
-	rm -f $@ && $(LN_S) $< .
-endif
-
 fe-connect.o: fe-connect.c $(top_builddir)/src/port/pg_config_paths.h
 
 $(top_builddir)/src/port/pg_config_paths.h:
diff --git a/src/interfaces/libpq/fe-connect.c b/src/interfaces/libpq/fe-connect.c
index ff4f4285d08..bdeeb02a225 100644
--- a/src/interfaces/libpq/fe-connect.c
+++ b/src/interfaces/libpq/fe-connect.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/interfaces/libpq/fe-connect.c,v 1.319 2005/08/23 20:48:46 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/interfaces/libpq/fe-connect.c,v 1.320 2005/08/23 21:02:03 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -55,8 +55,12 @@
 #endif
 
 #ifdef ENABLE_THREAD_SAFETY
+#ifdef WIN32
+#include "pthread-win32.h"
+#else
 #include <pthread.h>
 #endif
+#endif
 
 #include "libpq/ip.h"
 #include "mb/pg_wchar.h"
diff --git a/src/interfaces/libpq/fe-exec.c b/src/interfaces/libpq/fe-exec.c
index eeb4819fb00..288cfe56cc9 100644
--- a/src/interfaces/libpq/fe-exec.c
+++ b/src/interfaces/libpq/fe-exec.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/interfaces/libpq/fe-exec.c,v 1.173 2005/08/23 20:48:47 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/interfaces/libpq/fe-exec.c,v 1.174 2005/08/23 21:02:03 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -2156,25 +2156,16 @@ PQoidValue(const PGresult *res)
 	char	   *endptr = NULL;
 	unsigned long result;
 
-	if (!res || !res->cmdStatus || strncmp(res->cmdStatus, "INSERT ", 7) != 0)
+	if (!res || 
+        !res->cmdStatus || 
+        strncmp(res->cmdStatus, "INSERT ", 7) != 0 ||
+        res->cmdStatus[7] < '0' || 
+        res->cmdStatus[7] > '9')
 		return InvalidOid;
 
-#ifdef WIN32
-	SetLastError(0);
-#else
-	errno = 0;
-#endif
 	result = strtoul(res->cmdStatus + 7, &endptr, 10);
 
-	if (!endptr || (*endptr != ' ' && *endptr != '\0')
-#ifndef WIN32
-	/*
-	 *	On WIN32, errno is not thread-safe and GetLastError() isn't set by
-	 *	strtoul(), so we can't check on this platform.
-	 */
- || errno == ERANGE
-#endif
-		)
+	if (!endptr || (*endptr != ' ' && *endptr != '\0'))
 		return InvalidOid;
 	else
 		return (Oid) result;
diff --git a/src/interfaces/libpq/fe-misc.c b/src/interfaces/libpq/fe-misc.c
index f4ae2ca2d93..b31c3a9613d 100644
--- a/src/interfaces/libpq/fe-misc.c
+++ b/src/interfaces/libpq/fe-misc.c
@@ -23,7 +23,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/interfaces/libpq/fe-misc.c,v 1.118 2005/08/23 20:48:47 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/interfaces/libpq/fe-misc.c,v 1.119 2005/08/23 21:02:03 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1133,7 +1133,11 @@ libpq_gettext(const char *msgid)
 	if (!already_bound)
 	{
 		/* dgettext() preserves errno, but bindtextdomain() doesn't */
-		int		save_errno = errno;
+#ifdef WIN32
+		int		save_errno = GetLastError();
+#else
+		int		save_errno = errno;    
+#endif
 		const char *ldir;
 
 		already_bound = true;
diff --git a/src/interfaces/libpq/fe-print.c b/src/interfaces/libpq/fe-print.c
index 38bc1ceee6c..a83004328c1 100644
--- a/src/interfaces/libpq/fe-print.c
+++ b/src/interfaces/libpq/fe-print.c
@@ -10,7 +10,7 @@
  * didn't really belong there.
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/interfaces/libpq/fe-print.c,v 1.62 2005/08/23 20:48:47 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/interfaces/libpq/fe-print.c,v 1.63 2005/08/23 21:02:03 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -88,7 +88,7 @@ PQprint(FILE *fout, const PGresult *res, const PQprintOpt *po)
 		int			total_line_length = 0;
 		int			usePipe = 0;
 		char	   *pagerenv;
-#ifdef ENABLE_THREAD_SAFETY
+#if defined(ENABLE_THREAD_SAFETY) && !defined(WIN32)
 		sigset_t	osigset;
 		bool		sigpipe_masked = false;
 		bool		sigpipe_pending;
@@ -189,14 +189,14 @@ PQprint(FILE *fout, const PGresult *res, const PQprintOpt *po)
 				if (fout)
 				{
 					usePipe = 1;
+#ifndef WIN32
 #ifdef ENABLE_THREAD_SAFETY
 					if (pq_block_sigpipe(&osigset, &sigpipe_pending) == 0)
 						sigpipe_masked = true;
 #else
-#ifndef WIN32
 					oldsigpipehandler = pqsignal(SIGPIPE, SIG_IGN);
-#endif
-#endif
+#endif /* ENABLE_THREAD_SAFETY */
+#endif /* WIN32 */
 				}
 				else
 					fout = stdout;
@@ -311,16 +311,15 @@ PQprint(FILE *fout, const PGresult *res, const PQprintOpt *po)
 			_pclose(fout);
 #else
 			pclose(fout);
-#endif
+            
 #ifdef ENABLE_THREAD_SAFETY
 			/* we can't easily verify if EPIPE occurred, so say it did */
 			if (sigpipe_masked)
 				pq_reset_sigpipe(&osigset, sigpipe_pending, true);
 #else
-#ifndef WIN32
 			pqsignal(SIGPIPE, oldsigpipehandler);
-#endif
-#endif
+#endif /* ENABLE_THREAD_SAFETY */
+#endif /* WIN32 */
 		}
 		if (po->html3 && !po->expanded)
 			fputs("</table>\n", fout);
diff --git a/src/interfaces/libpq/fe-secure.c b/src/interfaces/libpq/fe-secure.c
index 0852047d8db..c3cfe42ff32 100644
--- a/src/interfaces/libpq/fe-secure.c
+++ b/src/interfaces/libpq/fe-secure.c
@@ -11,7 +11,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/interfaces/libpq/fe-secure.c,v 1.69 2005/08/23 20:48:47 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/interfaces/libpq/fe-secure.c,v 1.70 2005/08/23 21:02:03 momjian Exp $
  *
  * NOTES
  *	  [ Most of these notes are wrong/obsolete, but perhaps not all ]
@@ -103,8 +103,12 @@
 #include <sys/stat.h>
 
 #ifdef ENABLE_THREAD_SAFETY
+#ifdef WIN32
+#include "pthread-win32.h"
+#else
 #include <pthread.h>
 #endif
+#endif
 
 #ifndef HAVE_STRDUP
 #include "strdup.h"
@@ -388,20 +392,21 @@ ssize_t
 pqsecure_write(PGconn *conn, const void *ptr, size_t len)
 {
 	ssize_t		n;
-	
+    
+#ifndef WIN32	
 #ifdef ENABLE_THREAD_SAFETY
 	sigset_t	osigmask;
 	bool		sigpipe_pending;
 	bool		got_epipe = false;
 	
+
 	if (pq_block_sigpipe(&osigmask, &sigpipe_pending) < 0)
 		return -1;
 #else
-#ifndef WIN32
 	pqsigfunc	oldsighandler = pqsignal(SIGPIPE, SIG_IGN);
-#endif
-#endif
-
+#endif /* ENABLE_THREAD_SAFETY */
+#endif /* WIN32 */
+    
 #ifdef USE_SSL
 	if (conn->ssl)
 	{
@@ -431,7 +436,7 @@ pqsecure_write(PGconn *conn, const void *ptr, size_t len)
 
 					if (n == -1)
 					{
-#ifdef ENABLE_THREAD_SAFETY
+#if defined(ENABLE_THREAD_SAFETY) && !defined(WIN32)
 						if (SOCK_ERRNO == EPIPE)
 							got_epipe = true;
 #endif
@@ -473,19 +478,19 @@ pqsecure_write(PGconn *conn, const void *ptr, size_t len)
 #endif
 	{
 		n = send(conn->sock, ptr, len, 0);
-#ifdef ENABLE_THREAD_SAFETY
+#if defined(ENABLE_THREAD_SAFETY) && !defined(WIN32)
 		if (n < 0 && SOCK_ERRNO == EPIPE)
 			got_epipe = true;
 #endif
 	}
-
+    
+#ifndef WIN32
 #ifdef ENABLE_THREAD_SAFETY
 	pq_reset_sigpipe(&osigmask, sigpipe_pending, got_epipe);
 #else
-#ifndef WIN32
 	pqsignal(SIGPIPE, oldsighandler);
-#endif
-#endif
+#endif /* ENABLE_THREAD_SAFETY */
+#endif /* WIN32 */
 
 	return n;
 }
@@ -1232,7 +1237,7 @@ PQgetssl(PGconn *conn)
 
 #endif   /* USE_SSL */
 
-#ifdef ENABLE_THREAD_SAFETY
+#if defined(ENABLE_THREAD_SAFETY) && !defined(WIN32)
 
 /*
  *	Block SIGPIPE for this thread.  This prevents send()/write() from exiting
diff --git a/src/interfaces/libpq/libpq-int.h b/src/interfaces/libpq/libpq-int.h
index d8687a8a88e..3eb66dea2dc 100644
--- a/src/interfaces/libpq/libpq-int.h
+++ b/src/interfaces/libpq/libpq-int.h
@@ -12,7 +12,7 @@
  * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/interfaces/libpq/libpq-int.h,v 1.106 2005/08/23 20:48:47 momjian Exp $
+ * $PostgreSQL: pgsql/src/interfaces/libpq/libpq-int.h,v 1.107 2005/08/23 21:02:03 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -30,7 +30,11 @@
 #endif
 
 #ifdef ENABLE_THREAD_SAFETY
+#ifdef WIN32
+#include "pthread-win32.h"
+#else
 #include <pthread.h>
+#endif
 #include <signal.h>
 #endif
 
@@ -481,7 +485,7 @@ extern void pqsecure_close(PGconn *);
 extern ssize_t pqsecure_read(PGconn *, void *ptr, size_t len);
 extern ssize_t pqsecure_write(PGconn *, const void *ptr, size_t len);
 
-#ifdef ENABLE_THREAD_SAFETY
+#if defined(ENABLE_THREAD_SAFETY) && !defined(WIN32)
 extern int	pq_block_sigpipe(sigset_t *osigset, bool *sigpipe_pending);
 extern void pq_reset_sigpipe(sigset_t *osigset, bool sigpipe_pending,
 							 bool got_epipe);
diff --git a/src/interfaces/libpq/pthread-win32.c b/src/interfaces/libpq/pthread-win32.c
index e5be8a95331..eb0862f1fa3 100644
--- a/src/interfaces/libpq/pthread-win32.c
+++ b/src/interfaces/libpq/pthread-win32.c
@@ -5,14 +5,14 @@
 *
 * Copyright (c) 2004-2005, PostgreSQL Global Development Group
 * IDENTIFICATION
-*	$PostgreSQL: pgsql/src/interfaces/libpq/pthread-win32.c,v 1.7 2005/08/23 20:48:47 momjian Exp $
+*	$PostgreSQL: pgsql/src/interfaces/libpq/pthread-win32.c,v 1.8 2005/08/23 21:02:03 momjian Exp $
 *
 *-------------------------------------------------------------------------
 */
 
 
 #include <windows.h>
-#include "pthread.h"
+#include "pthread-win32.h"
 
 HANDLE
 pthread_self()
diff --git a/src/tools/thread/README b/src/tools/thread/README
index d5b9dab7924..107699610ef 100644
--- a/src/tools/thread/README
+++ b/src/tools/thread/README
@@ -14,3 +14,36 @@ If your platform requires special thread flags that are not tested by
 /config/acx_pthread.m4, add PTHREAD_CFLAGS and PTHREAD_LIBS defines to 
 your template/${port} file.
 
+Windows Systems
+===============
+
+Windows systems do not vary in their thread-safeness in the same way that
+other systems might, nor do they generally have pthreads installed, hence 
+on Windows this test is skipped by the configure program (pthreads is 
+required by the test program, but not PostgreSQL itself). If you do wish
+to test your system however, you can do so as follows:
+
+1) Install pthreads in you Mingw/Msys environment. You can download pthreads
+   from ftp://sources.redhat.com/pub/pthreads-win32/.
+   
+2) Build the test program:
+
+   gcc -o thread_test.exe \
+    -D_REENTRANT \
+    -D_THREAD_SAFE \
+    -D_POSIX_PTHREAD_SEMANTICS \
+    -I../../../src/include/port/win32 \
+    thread_test.c \
+    -lwsock32 \
+    -lpthreadgc2
+
+3) Run thread_test.exe. You should see output like:
+
+    dpage@PC30:/cvs/pgsql/src/tools/thread$ ./thread_test
+    Your GetLastError() is thread-safe.
+    Your system uses strerror() which is thread-safe.
+    getpwuid_r()/getpwuid() are not applicable to Win32 platforms.
+    Your system uses gethostbyname which is thread-safe.
+
+    Your platform is thread-safe.
+
diff --git a/src/tools/thread/thread_test.c b/src/tools/thread/thread_test.c
index 5340376934c..70babc09cde 100644
--- a/src/tools/thread/thread_test.c
+++ b/src/tools/thread/thread_test.c
@@ -6,7 +6,7 @@
  * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- *	$PostgreSQL: pgsql/src/tools/thread/thread_test.c,v 1.39 2005/08/23 20:48:47 momjian Exp $
+ *	$PostgreSQL: pgsql/src/tools/thread/thread_test.c,v 1.40 2005/08/23 21:02:05 momjian Exp $
  *
  *	This program tests to see if your standard libc functions use
  *	pthread_setspecific()/pthread_getspecific() to be thread-safe.
@@ -20,7 +20,7 @@
  *-------------------------------------------------------------------------
  */
 
-#ifndef IN_CONFIGURE
+#if !defined(IN_CONFIGURE) && !defined(WIN32)
 #include "postgres.h"
 #else
 /* From src/include/c.h" */
@@ -47,12 +47,43 @@ typedef char bool;
 #include <fcntl.h>
 #include <errno.h>
 
+
+/******************************************************************
+ * Windows Hacks
+ *****************************************************************/
+ 
+#ifdef WIN32
+#define MAXHOSTNAMELEN 63
+#include <winsock2.h>
+
+int mkstemp(char *template);
+
+int
+mkstemp(char *template)
+{
+	FILE *foo;
+
+	mktemp(template);
+	foo = fopen(template, "rw");
+	if (!foo)
+		return -1;
+	else
+		return (int)foo;
+}
+
+#endif
+
+/******************************************************************
+ * End Windows Hacks
+ *****************************************************************/
+
+
 /* Test for POSIX.1c 2-arg sigwait() and fail on single-arg version */
 #include <signal.h>
 int sigwait(const sigset_t *set, int *sig);
 
 
-#if !defined(ENABLE_THREAD_SAFETY) && !defined(IN_CONFIGURE)
+#if !defined(ENABLE_THREAD_SAFETY) && !defined(IN_CONFIGURE) && !(defined(WIN32))
 int
 main(int argc, char *argv[])
 {
@@ -69,8 +100,13 @@ main(int argc, char *argv[])
 static void		func_call_1(void);
 static void		func_call_2(void);
 
+#ifdef WIN32
+#define		TEMP_FILENAME_1 "thread_test.1.XXXXXX"
+#define		TEMP_FILENAME_2 "thread_test.2.XXXXXX"
+#else
 #define		TEMP_FILENAME_1 "/tmp/thread_test.1.XXXXXX"
 #define		TEMP_FILENAME_2 "/tmp/thread_test.2.XXXXXX"
+#endif
 
 static char	   *temp_filename_1;
 static char	   *temp_filename_2;
@@ -89,11 +125,13 @@ static char	   *strerror_p2;
 static bool		strerror_threadsafe = false;
 #endif
 
+#ifndef WIN32
 #ifndef HAVE_GETPWUID_R
 static struct passwd *passwd_p1;
 static struct passwd *passwd_p2;
 static bool		getpwuid_threadsafe = false;
 #endif
+#endif
 
 #if !defined(HAVE_GETADDRINFO) && !defined(HAVE_GETHOSTBYNAME_R)
 static struct hostent *hostent_p1;
@@ -108,8 +146,12 @@ int
 main(int argc, char *argv[])
 {
 	pthread_t	thread1,
-				thread2;
-	int			fd;
+			thread2;
+	int		fd;
+#ifdef WIN32
+	WSADATA		wsaData;
+	int		err;
+#endif
 
 	if (argc > 1)
 	{
@@ -123,6 +165,14 @@ main(int argc, char *argv[])
 	dup(5);
 #endif
 
+#ifdef WIN32
+	err = WSAStartup(MAKEWORD(1, 1), &wsaData);
+	if (err != 0) {
+		fprintf(stderr, "Cannot start the network subsystem - %d**\nexiting\n", err);
+		exit(1);
+	}
+#endif
+
 	/* Make temp filenames, might not have strdup() */
 	temp_filename_1 = malloc(strlen(TEMP_FILENAME_1) + 1);
 	strcpy(temp_filename_1, TEMP_FILENAME_1);
@@ -151,18 +201,23 @@ main(int argc, char *argv[])
 	while (thread1_done == 0 || thread2_done == 0)
 		sched_yield();			/* if this is a portability problem,
 								 * remove it */
-
+#ifdef WIN32
+	printf("Your GetLastError() is thread-safe.\n");
+#else
 	printf("Your errno is thread-safe.\n");
+#endif
 
 #ifndef HAVE_STRERROR_R
 	if (strerror_p1 != strerror_p2)
 		strerror_threadsafe = true;
 #endif
 
+#ifndef WIN32
 #ifndef HAVE_GETPWUID_R
 	if (passwd_p1 != passwd_p2)
 		getpwuid_threadsafe = true;
 #endif
+#endif
 
 #if !defined(HAVE_GETADDRINFO) && !defined(HAVE_GETHOSTBYNAME_R)
 	if (hostent_p1 != hostent_p2)
@@ -187,6 +242,7 @@ main(int argc, char *argv[])
 	}
 #endif
 
+#ifndef WIN32
 #ifdef HAVE_GETPWUID_R
 	printf("Your system has getpwuid_r();  it does not need getpwuid().\n");
 #else
@@ -199,6 +255,9 @@ main(int argc, char *argv[])
 		platform_is_threadsafe = false;
 	}
 #endif
+#else
+	printf("getpwuid_r()/getpwuid() are not applicable to Win32 platforms.\n");
+#endif
 
 #ifdef HAVE_GETADDRINFO
 	printf("Your system has getaddrinfo();  it does not need gethostbyname()\n"
@@ -238,14 +297,30 @@ func_call_1(void)
 	 !defined(HAVE_GETHOSTBYNAME_R))
 	void	   *p;
 #endif
-
+#ifdef WIN32
+    HANDLE h1;
+    HANDLE h2;
+#endif    
 	unlink(temp_filename_1);
+    
+    
 	/* create, then try to fail on exclusive create open */
+#ifdef WIN32
+    h1 = CreateFile(temp_filename_1, GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, 0, NULL);
+    h2 = CreateFile(temp_filename_1, GENERIC_WRITE, 0, NULL, CREATE_NEW, 0, NULL);
+	if (h1 == INVALID_HANDLE_VALUE || GetLastError() != ERROR_FILE_EXISTS)
+#else
 	if (open(temp_filename_1, O_RDWR | O_CREAT, 0600) < 0 ||
 		open(temp_filename_1, O_RDWR | O_CREAT | O_EXCL, 0600) >= 0)
+#endif
 	{
+#ifdef WIN32
+		fprintf(stderr, "Could not create file in current directory or\n");
+		fprintf(stderr, "Could not generate failure for create file in current directory **\nexiting\n");
+#else
 		fprintf(stderr, "Could not create file in /tmp or\n");
 		fprintf(stderr, "Could not generate failure for create file in /tmp **\nexiting\n");
+#endif
 		exit(1);
 	}
 
@@ -256,9 +331,17 @@ func_call_1(void)
 	errno1_set = 1;
 	while (errno2_set == 0)
 		sched_yield();
-	if (errno != EEXIST)
+#ifdef WIN32
+    if (GetLastError() != ERROR_FILE_EXISTS)
+#else
+	if (errno != EEXIST)    
+#endif
 	{
-		fprintf(stderr, "errno not thread-safe **\nexiting\n");
+#ifdef WIN32
+		fprintf(stderr, "GetLastError() not thread-safe **\nexiting\n");        
+#else
+		fprintf(stderr, "errno not thread-safe **\nexiting\n");         
+#endif    
 		unlink(temp_filename_1);
 		exit(1);
 	}
@@ -274,6 +357,7 @@ func_call_1(void)
 	 */
 #endif
 
+#ifndef WIN32
 #ifndef HAVE_GETPWUID_R
 	passwd_p1 = getpwuid(0);
 	p = getpwuid(1);
@@ -283,6 +367,7 @@ func_call_1(void)
 		passwd_p1 = NULL;		/* force thread-safe failure report */
 	}
 #endif
+#endif
 
 #if !defined(HAVE_GETADDRINFO) && !defined(HAVE_GETHOSTBYNAME_R)
 	/* threads do this in opposite order */
@@ -312,7 +397,12 @@ func_call_2(void)
 
 	unlink(temp_filename_2);
 	/* open non-existant file */
+#ifdef WIN32
+    CreateFile(temp_filename_2, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
+    if (GetLastError() != ERROR_FILE_NOT_FOUND)
+#else
 	if (open(temp_filename_2, O_RDONLY, 0600) >= 0)
+#endif
 	{
 		fprintf(stderr, "Read-only open succeeded without create **\nexiting\n");
 		exit(1);
@@ -325,9 +415,17 @@ func_call_2(void)
 	errno2_set = 1;
 	while (errno1_set == 0)
 		sched_yield();
-	if (errno != ENOENT)
+#ifdef WIN32
+    if (GetLastError() != ENOENT)
+#else
+	if (errno != ENOENT)    
+#endif
 	{
-		fprintf(stderr, "errno not thread-safe **\nexiting\n");
+#ifdef WIN32
+		fprintf(stderr, "GetLastError() not thread-safe **\nexiting\n");        
+#else
+		fprintf(stderr, "errno not thread-safe **\nexiting\n");         
+#endif
 		unlink(temp_filename_2);
 		exit(1);
 	}
@@ -343,6 +441,7 @@ func_call_2(void)
 	 */
 #endif
 
+#ifndef WIN32
 #ifndef HAVE_GETPWUID_R
 	passwd_p2 = getpwuid(2);
 	p = getpwuid(3);
@@ -352,6 +451,7 @@ func_call_2(void)
 		passwd_p2 = NULL;		/* force thread-safe failure report */
 	}
 #endif
+#endif
 
 #if !defined(HAVE_GETADDRINFO) && !defined(HAVE_GETHOSTBYNAME_R)
 	/* threads do this in opposite order */
-- 
GitLab