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