pgwin32_PQexec_v1.patch

application/octet-stream

Filename: pgwin32_PQexec_v1.patch
Type: application/octet-stream
Part: 0
Message: Re: walreceiver is uninterruptible on win32

Patch

Same data as JSON: GET /api/v1/attachments/:id/patch the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes. API reference →
Format: context
Series: patch v1
File+
contrib/dblink/dblink.c 4 0
contrib/dblink/Makefile 5 0
src/backend/port/win32/libpqbe/exports.txt 3 0
src/backend/port/win32/libpqbe/libpqbe.c 102 0
src/backend/port/win32/libpqbe/Makefile 36 0
src/backend/replication/libpqwalreceiver/libpqwalreceiver.c 4 0
src/backend/replication/libpqwalreceiver/Makefile 10 0
src/include/port/win32/libpqbe.h 23 0
src/Makefile 4 0
src/Makefile.global.in 15 0
*** a/contrib/dblink/Makefile
--- b/contrib/dblink/Makefile
***************
*** 20,22 **** top_builddir = ../..
--- 20,27 ----
  include $(top_builddir)/src/Makefile.global
  include $(top_srcdir)/contrib/contrib-global.mk
  endif
+ 
+ ifeq ($(PORTNAME), win32)
+ override PG_CPPFLAGS := -I$(libpqbe_srcdir) $(PG_CPPFLAGS)
+ override SHLIB_LINK := $(libpqbe) $(SHLIB_LINK)
+ endif
*** a/contrib/dblink/dblink.c
--- b/contrib/dblink/dblink.c
***************
*** 67,72 ****
--- 67,76 ----
  
  #include "dblink.h"
  
+ #ifdef WIN32
+ #include "port/win32/libpqbe.h"
+ #endif
+ 
  PG_MODULE_MAGIC;
  
  typedef struct remoteConn
*** a/src/Makefile
--- b/src/Makefile
***************
*** 21,26 **** all install installdirs uninstall distprep:
--- 21,27 ----
  	$(MAKE) -C backend/snowball $@
  	$(MAKE) -C include $@
  	$(MAKE) -C interfaces $@
+ 	$(MAKE) -C backend/port/win32/libpqbe $@
  	$(MAKE) -C backend/replication/libpqwalreceiver $@
  	$(MAKE) -C bin $@
  	$(MAKE) -C pl $@
***************
*** 52,57 **** clean:
--- 53,59 ----
  	$(MAKE) -C backend/snowball $@
  	$(MAKE) -C include $@
  	$(MAKE) -C interfaces $@
+ 	$(MAKE) -C backend/port/win32/libpqbe $@
  	$(MAKE) -C backend/replication/libpqwalreceiver $@
  	$(MAKE) -C bin $@
  	$(MAKE) -C pl $@
***************
*** 67,72 **** distclean maintainer-clean:
--- 69,75 ----
  	$(MAKE) -C backend/snowball $@
  	$(MAKE) -C include $@
  	$(MAKE) -C interfaces $@
+ 	$(MAKE) -C backend/port/win32/libpqbe $@
  	$(MAKE) -C backend/replication/libpqwalreceiver $@
  	$(MAKE) -C bin $@
  	$(MAKE) -C pl $@
***************
*** 82,87 **** coverage:
--- 85,91 ----
  	$(MAKE) -C backend/utils/mb/conversion_procs $@
  	$(MAKE) -C backend/snowball $@
  	$(MAKE) -C interfaces $@
+ 	$(MAKE) -C backend/port/win32/libpqbe $@
  	$(MAKE) -C backend/replication/libpqwalreceiver $@
  	$(MAKE) -C bin $@
  	$(MAKE) -C pl $@
*** a/src/Makefile.global.in
--- b/src/Makefile.global.in
***************
*** 395,400 **** else
--- 395,411 ----
  libpq_pgport = -L$(top_builddir)/src/port -lpgport $(libpq)
  endif
  
+ # This macro is for use by backend libraries that use libpq.
+ ifdef PGXS
+ libpqbe_srcdir = $(includedir)
+ libpqbe_builddir = $(libdir)
+ libpqbe = -L$(libdir) -lpqbe $(libpq)
+ else
+ libpqbe_srcdir = $(top_srcdir)/src/include/port/win32
+ libpqbe_builddir = $(top_builddir)/src/backend/port/win32/libpqbe
+ libpqbe = -L$(libpqbe_builddir) -lpqbe $(libpq)
+ endif
+ 
  
  submake-libpq:
  	$(MAKE) -C $(libpq_builddir) all
***************
*** 402,408 **** submake-libpq:
  submake-libpgport:
  	$(MAKE) -C $(top_builddir)/src/port all
  
! .PHONY: submake-libpq submake-libpgport
  
  
  ##########################################################################
--- 413,422 ----
  submake-libpgport:
  	$(MAKE) -C $(top_builddir)/src/port all
  
! submake-libpqbe: submake-libpq
! 	$(MAKE) -C $(libpqbe_builddir) all
! 
! .PHONY: submake-libpq submake-libpgport submake-libpqbe
  
  
  ##########################################################################
*** /dev/null
--- b/src/backend/port/win32/libpqbe/Makefile
***************
*** 0 ****
--- 1,36 ----
+ #-------------------------------------------------------------------------
+ #
+ # Makefile--
+ #    Makefile for src/backend/port/win32/libpqbe
+ #
+ # IDENTIFICATION
+ #    $PostgreSQL$
+ #
+ #-------------------------------------------------------------------------
+ 
+ subdir = src/backend/port/win32/libpqbe
+ top_builddir = ../../../../..
+ include $(top_builddir)/src/Makefile.global
+ 
+ override CPPFLAGS := -I$(srcdir) -I$(libpq_srcdir) $(CPPFLAGS)
+ 
+ OBJS = libpqbe.o
+ SHLIB_LINK = $(libpq)
+ NAME = libpqbe
+ 
+ SHLIB_EXPORTS = exports.txt
+ 
+ ifeq ($(PORTNAME),win32)
+ all: submake-libpq all-shared-lib
+ 
+ include $(top_srcdir)/src/Makefile.shlib
+ 
+ install: all installdirs install-lib
+ 
+ installdirs: installdirs-lib
+ 
+ uninstall: uninstall-lib
+ 
+ clean distclean maintainer-clean: clean-lib
+ 	rm -f $(OBJS)
+ endif
*** /dev/null
--- b/src/backend/port/win32/libpqbe/exports.txt
***************
*** 0 ****
--- 1,3 ----
+ # $PostgreSQL$
+ # Functions to be exported by libpqbe DLL
+ pgwin32_PQexec   1
*** /dev/null
--- b/src/backend/port/win32/libpqbe/libpqbe.c
***************
*** 0 ****
--- 1,102 ----
+ /*-------------------------------------------------------------------------
+  *
+  * libpqbe.c
+  *	  functions related to sending a query from the backend
+  *
+  * Portions Copyright (c) 2010-2010, PostgreSQL Global Development Group
+  *
+  *
+  * IDENTIFICATION
+  *	  $PostgreSQL$
+  *
+  *-------------------------------------------------------------------------
+  */
+ #include "postgres.h"
+ 
+ #include "libpq-fe.h"
+ #include "port/win32/libpqbe.h"
+ 
+ /*
+ * Send a query and wait for the results by using the asynchronous libpq
+ * functions and the backend version of select().
+ *
+ * On Windows, dblink and walreceiver must use this function instead of
+ * the blocking libpq functions like PQexec() since they use the vanilla
+ * select() and are uninterruptible by our emulated signals. On the other
+ * hand, this function is interruptible since it uses the signal emulation
+ * layer compatible select().
+  */
+ PGresult *
+ pgwin32_PQexec(PGconn *conn, const char *query)
+ {
+ 	PGresult   *result = NULL;
+ 	PGresult   *lastResult = NULL;
+ 
+ 	/*
+ 	 * Submit a query. Since we don't use non-blocking mode, this also
+ 	 * can block. But its risk is relatively small, so we ignore that
+ 	 * for now.
+ 	 */
+ 	if (!PQsendQuery(conn, query))
+ 		return NULL;
+ 
+ 	for (;;)
+ 	{
+ 		/*
+ 		 * Receive data until PQgetResult has been ready to get the
+ 		 * result without blocking.
+ 		 */
+ 		while (PQisBusy(conn))
+ 		{
+ 			int	ret;
+ 			int	sock = PQsocket(conn);
+ 			fd_set		input_mask;
+ 
+ 			if (sock < 0)
+ 				ereport(ERROR,
+ 						(errcode_for_socket_access(),
+ 						 errmsg("socket not open")));
+ 
+ 			FD_ZERO(&input_mask);
+ 			FD_SET		(sock, &input_mask);
+ 
+ 			ret = select(sock + 1, &input_mask, NULL, NULL, NULL);
+ 			if (ret == 0 || (ret < 0 && errno == EINTR))
+ 				continue;			/* interrupted */
+ 			if (ret < 0)
+ 				ereport(ERROR,
+ 						(errcode_for_socket_access(),
+ 						 errmsg("select() failed: %m")));
+ 			if (PQconsumeInput(conn) == 0)
+ 				return NULL;
+ 		}
+ 
+ 		/*
+ 		 * Emulate the PQexec()'s behavior of returning the last result,
+ 		 * if there's many.
+ 		 *
+ 		 * We don't try to concatenate error messages like PQexec() does.
+ 		 * Doesn't seem worth the effort.
+ 		 */
+ 		if ((result = PQgetResult(conn)) == NULL)
+ 			break;				/* query is complete */
+ 		if (lastResult)
+ 		{
+ 			if (PQresultStatus(lastResult) == PGRES_FATAL_ERROR &&
+ 				PQresultStatus(result) == PGRES_FATAL_ERROR)
+ 			{
+ 				PQclear(result);
+ 				result = lastResult;
+ 			}
+ 			else
+ 				PQclear(lastResult);
+ 		}
+ 		lastResult = result;
+ 		if (PQresultStatus(result) == PGRES_COPY_IN ||
+ 			PQresultStatus(result) == PGRES_COPY_OUT ||
+ 			PQstatus(conn) == CONNECTION_BAD)
+ 			break;
+ 	}
+ 
+ 	return lastResult;
+ }
*** a/src/backend/replication/libpqwalreceiver/Makefile
--- b/src/backend/replication/libpqwalreceiver/Makefile
***************
*** 15,24 **** include $(top_builddir)/src/Makefile.global
  override CPPFLAGS := -I$(srcdir) -I$(libpq_srcdir) $(CPPFLAGS)
  
  OBJS = libpqwalreceiver.o
  SHLIB_LINK = $(libpq)
  NAME = libpqwalreceiver
  
! all: submake-libpq all-shared-lib
  
  include $(top_srcdir)/src/Makefile.shlib
  
--- 15,33 ----
  override CPPFLAGS := -I$(srcdir) -I$(libpq_srcdir) $(CPPFLAGS)
  
  OBJS = libpqwalreceiver.o
+ ifeq ($(PORTNAME), win32)
+ override CPPFLAGS := -I$(libpqbe_srcdir) $(CPPFLAGS)
+ SHLIB_LINK = $(libpqbe)
+ else
  SHLIB_LINK = $(libpq)
+ endif
  NAME = libpqwalreceiver
  
! ifeq ($(PORTNAME), win32)
! all:	submake-libpqbe	all-shared-lib
! else
! all:	submake-libpq	all-shared-lib
! endif
  
  include $(top_srcdir)/src/Makefile.shlib
  
*** a/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c
--- b/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c
***************
*** 25,30 ****
--- 25,34 ----
  #include "replication/walreceiver.h"
  #include "utils/builtins.h"
  
+ #ifdef WIN32
+ #include "port/win32/libpqbe.h"
+ #endif
+ 
  #ifdef HAVE_POLL_H
  #include <poll.h>
  #endif
*** /dev/null
--- b/src/include/port/win32/libpqbe.h
***************
*** 0 ****
--- 1,23 ----
+ /*-------------------------------------------------------------------------
+  *
+  * libpqbe.h
+  *	  functions related to sending a query from the backend
+  *
+  * Portions Copyright (c) 2010-2010, PostgreSQL Global Development Group
+  *
+  *
+  * IDENTIFICATION
+  *	  $PostgreSQL$
+  *
+  *-------------------------------------------------------------------------
+  */
+ 
+ #ifndef LIBPQBE_H
+ #define LIBPQBE_H
+ 
+ #include "libpq-fe.h"
+ 
+ #define PQexec(conn, query) pgwin32_PQexec(conn, query)
+ PGresult *pgwin32_PQexec(PGconn *conn, const char *query);
+ 
+ #endif   /* LIBPQBE_H */