On Wed, Oct 15, 2014 at 12:53:03AM -0400, Noah Misch wrote:
> On Tue, Oct 14, 2014 at 07:07:17PM -0400, Tom Lane wrote:
> > Dave Page <dp...@pgadmin.org> writes:
> > > On Tue, Oct 14, 2014 at 11:38 PM, Tom Lane <t...@sss.pgh.pa.us> wrote:
> > >> I think we're hoping that somebody will step up and investigate how
> > >> narwhal's problem might be fixed.
> 
> I have planned to look at reproducing narwhal's problem once the dust settles
> on orangutan, but I wouldn't mind if narwhal went away instead.

> > No argument here.  I would kind of like to have more than zero
> > understanding of *why* it's failing, just in case there's more to it
> > than "oh, probably a bug in this old toolchain".  But finding that out
> > might well take significant time, and in the end not tell us anything
> > very useful.
> 
> Agreed on all those points.

I reproduced narwhal's problem using its toolchain on another 32-bit Windows
Server 2003 system.  The crash happens at the SHGetFolderPath() call in
pqGetHomeDirectory().  A program can acquire that function via shfolder.dll or
via shell32.dll; we've used the former method since commit 889f038, for better
compatibility[1] with Windows NT 4.0.  On this system, shfolder.dll's version
loads and unloads shell32.dll.  In PostgreSQL built using this older compiler,
shfolder.dll:SHGetFolderPath() unloads libpq in addition to unloading shell32!
That started with commit 846e91e.  I don't expect to understand the mechanism
behind it, but I recommend we switch back to linking libpq with shell32.dll.
The MSVC build already does that in all supported branches, and it feels right
for the MinGW build to follow suit in 9.4+.  Windows versions that lack the
symbol in shell32.dll are now ancient history.


I happened to try the same contrib/dblink test suite on PostgreSQL built with
modern MinGW-w64 (i686-4.9.1-release-win32-dwarf-rt_v3-rev1).  That, too, gave
a crash-like symptom starting with commit 846e91e.  Specifically, a backend
that LOADed any module linked to libpq (libpqwalreceiver, dblink,
postgres_fdw) would suffer this after calling exit(0):

===
3056 2014-10-20 00:40:15.163 GMT LOG:  disconnection: session time: 0:00:00.515 
user=cyg_server database=template1 host=127.0.0.1 port=3936

This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information.

This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information.
9300 2014-10-20 00:40:15.163 GMT LOG:  server process (PID 3056) exited with 
exit code 3
===

The mechanism turned out to be disjoint from the mechanism behind the
ancient-compiler crash.  Based on the functions called from exit(), my best
guess is that exit() encountered recursion and used something like an abort()
to escape.  (I can send the gdb transcript if anyone is curious to see the
gory details.)  The proximate cause was commit 846e91e allowing modules to use
shared libgcc.  A 32-bit libpq acquires 64-bit integer division from libgcc.
Passing -static-libgcc to the link restores the libgcc situation as it stood
before commit 846e91e.  The main beneficiary of shared libgcc is C++/Java
exception handling, so PostgreSQL doesn't care.  No doubt there's some deeper
bug in libgcc or in PostgreSQL; loading a module that links with shared libgcc
should not disrupt exit().  I'm content with this workaround.


Patches attached.  For readers inclined toward animal husbandry, we could
benefit from more MinGW buildfarm coverage.  There are three compiler strains
(classic MinGW, 32-bit MinGW-w64, 64-bit MinGW-w64) and three supported
Windows Server versions.

[1] 
http://www.postgresql.org/message-id/flat/6bcb9d8a16ac4241919521715f4d8bce476...@algol.sollentuna.se
diff --git a/src/Makefile.global.in b/src/Makefile.global.in
index 0ffc1e8..3edc387 100644
--- a/src/Makefile.global.in
+++ b/src/Makefile.global.in
@@ -547,10 +547,9 @@ LIBOBJS = @LIBOBJS@
 
 LIBS := -lpgcommon -lpgport $(LIBS)
 
-# to make ws2_32.lib the last library, and always link with shfolder,
-# so SHGetFolderName isn't picked up from shell32.dll
+# to make ws2_32.lib the last library
 ifeq ($(PORTNAME),win32)
-LIBS += -lws2_32 -lshfolder
+LIBS += -lws2_32
 endif
 
 # Not really standard libc functions, used by the backend.
diff --git a/src/interfaces/ecpg/ecpglib/Makefile 
b/src/interfaces/ecpg/ecpglib/Makefile
index c99faac..43b76f6 100644
--- a/src/interfaces/ecpg/ecpglib/Makefile
+++ b/src/interfaces/ecpg/ecpglib/Makefile
@@ -39,11 +39,6 @@ SHLIB_PREREQS = submake-libpq submake-pgtypeslib
 
 SHLIB_EXPORTS = exports.txt
 
-ifeq ($(PORTNAME), win32)
-# Link to shfolder.dll instead of shell32.dll
-SHLIB_LINK += -lshfolder
-endif
-
 PKG_CONFIG_REQUIRES_PRIVATE = libpq libpgtypes
 
 all: all-lib
diff --git a/src/interfaces/libpq/Makefile b/src/interfaces/libpq/Makefile
index 145e3e8..18d9b85 100644
--- a/src/interfaces/libpq/Makefile
+++ b/src/interfaces/libpq/Makefile
@@ -74,7 +74,7 @@ else
 SHLIB_LINK += $(filter -lcrypt -ldes -lcom_err -lcrypto -lk5crypto -lkrb5 
-lgssapi32 -lssl -lsocket -lnsl -lresolv -lintl $(PTHREAD_LIBS), $(LIBS)) 
$(LDAP_LIBS_FE)
 endif
 ifeq ($(PORTNAME), win32)
-SHLIB_LINK += -lshfolder -lws2_32 -lsecur32 $(filter -leay32 -lssleay32 
-lcomerr32 -lkrb5_32, $(LIBS))
+SHLIB_LINK += -lshell32 -lws2_32 -lsecur32 $(filter -leay32 -lssleay32 
-lcomerr32 -lkrb5_32, $(LIBS))
 endif
 
 SHLIB_EXPORTS = exports.txt
diff --git a/src/interfaces/libpq/win32.mak b/src/interfaces/libpq/win32.mak
index 39a0bc9..1b71ebd 100644
--- a/src/interfaces/libpq/win32.mak
+++ b/src/interfaces/libpq/win32.mak
@@ -214,7 +214,7 @@ CPP_SBRS=.
 RSC_PROJ=/l 0x409 /fo"$(INTDIR)\libpq.res"
 
 LINK32=link.exe
-LINK32_FLAGS=kernel32.lib user32.lib advapi32.lib shfolder.lib ws2_32.lib 
secur32.lib $(SSL_LIBS)  $(KFW_LIB) $(ADD_SECLIB) \
+LINK32_FLAGS=kernel32.lib user32.lib advapi32.lib shell32.lib ws2_32.lib 
secur32.lib $(SSL_LIBS)  $(KFW_LIB) $(ADD_SECLIB) \
  /nologo /subsystem:windows /dll $(LOPT) /incremental:no \
  /pdb:"$(OUTDIR)\libpqdll.pdb" /machine:$(CPU) \
  /out:"$(OUTDIR)\$(OUTFILENAME).dll"\
diff --git a/src/port/path.c b/src/port/path.c
index 3789205..4f2b152 100644
--- a/src/port/path.c
+++ b/src/port/path.c
@@ -785,9 +785,11 @@ get_home_path(char *ret_path)
        char       *tmppath;
 
        /*
-        * Note: We use getenv here because the more modern
-        * SHGetSpecialFolderPath() will force us to link with shell32.lib which
-        * eats valuable desktop heap.
+        * Note: We use getenv() here because the more modern SHGetFolderPath()
+        * would force the backend to link with shell32.lib, which eats valuable
+        * desktop heap.  XXX This function is used only in psql, which already
+        * brings in shell32 via libpq.  Moving this function to its own file
+        * would keep it out of the backend, freeing it from this concern.
         */
        tmppath = getenv("APPDATA");
        if (!tmppath)
diff --git a/src/Makefile.shlib b/src/Makefile.shlib
index 0bf3a17..c97835f 100644
--- a/src/Makefile.shlib
+++ b/src/Makefile.shlib
@@ -371,16 +371,21 @@ else
 
 $(stlib): $(shlib) ;
 
+# A backend that loads a module linked with libgcc_s_dw2-1.dll will exit
+# uncleanly, hence -static-libgcc.  (Last verified with MinGW-w64 compilers
+# from i686-4.9.1-release-win32-dwarf-rt_v3-rev1.)  Shared libgcc has better
+# exception support, but PostgreSQL does not use language-provided exceptions.
+#
 # If SHLIB_EXPORTS is set, the rules below will build a .def file from that.
 # Else we just use --export-all-symbols.
 ifeq (,$(SHLIB_EXPORTS))
 $(shlib): $(OBJS) | $(SHLIB_PREREQS)
-       $(CC) $(CFLAGS)  -shared -o $@  $(OBJS) $(LDFLAGS) $(LDFLAGS_SL) 
$(SHLIB_LINK) $(LIBS) -Wl,--export-all-symbols -Wl,--out-implib=$(stlib)
+       $(CC) $(CFLAGS)  -shared -static-libgcc -o $@  $(OBJS) $(LDFLAGS) 
$(LDFLAGS_SL) $(SHLIB_LINK) $(LIBS) -Wl,--export-all-symbols 
-Wl,--out-implib=$(stlib)
 else
 DLL_DEFFILE = lib$(NAME)dll.def
 
 $(shlib): $(OBJS) $(DLL_DEFFILE) | $(SHLIB_PREREQS)
-       $(CC) $(CFLAGS)  -shared -o $@  $(OBJS) $(DLL_DEFFILE) $(LDFLAGS) 
$(LDFLAGS_SL) $(SHLIB_LINK) $(LIBS) -Wl,--out-implib=$(stlib)
+       $(CC) $(CFLAGS)  -shared -static-libgcc -o $@  $(OBJS) $(DLL_DEFFILE) 
$(LDFLAGS) $(LDFLAGS_SL) $(SHLIB_LINK) $(LIBS) -Wl,--out-implib=$(stlib)
 endif
 
 endif # PORTNAME == cgywin
diff --git a/src/makefiles/Makefile.win32 b/src/makefiles/Makefile.win32
index 73f0767..b93f780 100644
--- a/src/makefiles/Makefile.win32
+++ b/src/makefiles/Makefile.win32
@@ -76,4 +76,4 @@ win32ver.o: win32ver.rc
 
 # Rule for building a shared library from a single .o file
 %.dll: %.o $(WIN32RES)
-       $(CC) $(CFLAGS) -shared -o $@ $^ -Wl,--export-all-symbols $(LDFLAGS) 
$(LDFLAGS_SL) $(BE_DLLLIBS)
+       $(CC) $(CFLAGS) -shared -static-libgcc -o $@ $^ 
-Wl,--export-all-symbols $(LDFLAGS) $(LDFLAGS_SL) $(BE_DLLLIBS)
-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to