Thread: Problem with ControlFileData structure being ABI dependent

Problem with ControlFileData structure being ABI dependent

From
Gregory Stark
Date:
In trying to run a benchmark comparing mingw with VC++ builds Dave discovered
that if you initdb with one and try to run with the other you get a message
saying "incorrect checksum in control file" rather than the more appropriate
and friendly "database files are incompatible with server".

This is because of (at least) two changes in the ABI between the runtimes used
by mingw and VC++. 1) Enums are apparently 8 bytes on VC++ but 4 bytes on
mingw and 2) time_t is 8 bytes on VC++ but 4 bytes on mingw.

To get the right message we could add the size of the control file (or
offsetof(crc)) to the control file itself near the top and check it before the
checksum. That would be an initdb though which would be annoying at this
point. I think we should do this at the next opportunity though.

But I'm a bit concerned about change in ABI between mingw and VC++. I thought
these two used the same ABI. Are we sure Slony et al don't use time_t or enums
or anything else which may have changed between these two runtimes?

--  Gregory Stark EnterpriseDB          http://www.enterprisedb.com Ask me about EnterpriseDB's Slony Replication
support!


Re: Problem with ControlFileData structure being ABI dependent

From
Dave Page
Date:
Gregory Stark wrote:
> This is because of (at least) two changes in the ABI between the runtimes used
> by mingw and VC++. 1) Enums are apparently 8 bytes on VC++ but 4 bytes on
> mingw and 2) time_t is 8 bytes on VC++ but 4 bytes on mingw.

For the record:

Mingw
=====

WARNING:  sizeof(ControlFileData)=392
WARNING:  offsetof(state)=16
WARNING:  offsetof(time)=20
WARNING:  offsetof(checkPoint)=24
WARNING:  offsetof(prevCheckPoint)=32
WARNING:  offsetof(checkPointCopy)=40
WARNING:  offsetof(minRecoveryPoint)=76
WARNING:  offsetof(maxAlign)=84
WARNING:  offsetof(floatFormat)=88
WARNING:  offsetof(blcksz)=96
WARNING:  offsetof(relseg)=100
WARNING:  offsetof(xlog)=104
WARNING:  offsetof(xlog)=108
WARNING:  offsetof(nameDataLen)=112
WARNING:  offsetof(indexMaxKeys)=116
WARNING:  offsetof(toast)=120
WARNING:  offsetof(enableIntTimes)=124
WARNING:  offsetof(localeBuflen)=128
WARNING:  offsetof(lc)=132
WARNING:  offsetof(lc)=260
WARNING:  offsetof(crc)=388
WARNING:  crc = 3643130025

VC++
====

WARNING:  sizeof(ControlFileData)=408
WARNING:  offsetof(state)=16
WARNING:  offsetof(time)=24
WARNING:  offsetof(checkPoint)=32
WARNING:  offsetof(prevCheckPoint)=40
WARNING:  offsetof(checkPointCopy)=48
WARNING:  offsetof(minRecoveryPoint)=88
WARNING:  offsetof(maxAlign)=96
WARNING:  offsetof(floatFormat)=104
WARNING:  offsetof(blcksz)=112
WARNING:  offsetof(relseg)=116
WARNING:  offsetof(xlog)=120
WARNING:  offsetof(xlog)=124
WARNING:  offsetof(nameDataLen)=128
WARNING:  offsetof(indexMaxKeys)=132
WARNING:  offsetof(toast)=136
WARNING:  offsetof(enableIntTimes)=140
WARNING:  offsetof(localeBuflen)=144
WARNING:  offsetof(lc)=148
WARNING:  offsetof(lc)=276
WARNING:  offsetof(crc)=404
WARNING:  crc = 2595209512

/D


Re: Problem with ControlFileData structure being ABI dependent

From
Rainer Bauer
Date:
Gregory Stark wrote:

>This is because of (at least) two changes in the ABI between the runtimes used
>by mingw and VC++.
> 1) Enums are apparently 8 bytes on VC++ but 4 bytes on mingw

They are 4 bytes here on my 32 bit WinXP machine with VS2005SP1.

> 2) time_t is 8 bytes on VC++ but 4 bytes on mingw.

Not sure whether an 8 byte time_t is now required by postgres. But you can get
the old behaviour by defining _USE_32BIT_TIME_T.

Rainer


Re: Problem with ControlFileData structure being ABI dependent

From
Gregory Stark
Date:
"Rainer Bauer" <usenet@munnin.com> writes:

> Gregory Stark wrote:
>
>>This is because of (at least) two changes in the ABI between the runtimes used
>>by mingw and VC++.
>> 1) Enums are apparently 8 bytes on VC++ but 4 bytes on mingw
>
> They are 4 bytes here on my 32 bit WinXP machine with VS2005SP1.

Oh, I bet it's not the enum which is 8 bytes but that the time_t required
8-byte alignment so there's 4 bytes of padding before it.

>> 2) time_t is 8 bytes on VC++ but 4 bytes on mingw.
>
> Not sure whether an 8 byte time_t is now required by postgres. But you can get
> the old behaviour by defining _USE_32BIT_TIME_T.

Ugh.

The immediate problem is that a database initialized with with MSVCC can't be
run under mingw and vice versa. That's not necessarily important but it does
seem like it would be nice.

The looming problem is that you won't be able to use any libraries or 3rd
party tools which use time_t in their interface unless you build with the same
size time_t as they do. I don't know how're expected to find out that a .so
you're handed has a different size time_t.

--  Gregory Stark EnterpriseDB          http://www.enterprisedb.com Ask me about EnterpriseDB's RemoteDBA services!


Re: Problem with ControlFileData structure being ABI dependent

From
Rainer Bauer
Date:
Gregory Stark wrote:

>The looming problem is that you won't be able to use any libraries or 3rd
>party tools which use time_t in their interface unless you build with the same
>size time_t as they do. I don't know how're expected to find out that a .so
>you're handed has a different size time_t.

But that problem is already present if you try to link your VS2005 code to the
mingw build, isn't it? Respectively you will run into this problem when
upgrading to the MSVCC  build version 8.3.

Anyway, my original message was only intended as a comment, since I have no
idea whether time_t is only used internally or whether it's publically
exposed.

Rainer


Re: Problem with ControlFileData structure being ABI dependent

From
Tom Lane
Date:
Gregory Stark <stark@enterprisedb.com> writes:
> Oh, I bet it's not the enum which is 8 bytes but that the time_t required
> 8-byte alignment so there's 4 bytes of padding before it.

That makes more sense --- I was having a hard time imagining why anyone
would need 64-bit enums, let alone why that would silently become the
default.

>> Not sure whether an 8 byte time_t is now required by postgres. But you can get
>> the old behaviour by defining _USE_32BIT_TIME_T.

> Ugh.

> The looming problem is that you won't be able to use any libraries or
> 3rd party tools which use time_t in their interface unless you build
> with the same size time_t as they do.

AFAIK, time_t is a Unix-ism, so it's pretty unlikely to be used in the
APIs of anything on Windows.

I guess my advice would be to see if we can define _USE_32BIT_TIME_T
in port/win32.h and make it go away that way.  It'd definitely be nice
if MSVC and Mingw builds weren't binary-incompatible.

In the long run we should probably fix this by getting rid of use of
time_t on-disk in favor of TimestampTz.  I had partially done this in
8.3 by removing it from WAL commit records, but it's still there in
checkpoints and hence in pg_control.  I think it's too late for 8.3
though (unless maybe we hit another reason for a forced initdb, which
I sure hope we don't).
        regards, tom lane


Re: Problem with ControlFileData structure being ABI dependent

From
Dave Page
Date:
Tom Lane wrote:
> AFAIK, time_t is a Unix-ism, so it's pretty unlikely to be used in the
> APIs of anything on Windows.

Oh, it is.

> I guess my advice would be to see if we can define _USE_32BIT_TIME_T
> in port/win32.h and make it go away that way.  It'd definitely be nice
> if MSVC and Mingw builds weren't binary-incompatible.

The attached patch defines it in the MSVC project files along with the
other API-config related macros. It fixes all the offsets so they match
mingw, but the CRC is still different for some as-yet unknown reason...

VC++ with patch:

WARNING:  sizeof(ControlFileData)=392
WARNING:  offsetof(state)=16
WARNING:  offsetof(time)=20
WARNING:  offsetof(checkPoint)=24
WARNING:  offsetof(prevCheckPoint)=32
WARNING:  offsetof(checkPointCopy)=40
WARNING:  offsetof(minRecoveryPoint)=76
WARNING:  offsetof(maxAlign)=84
WARNING:  offsetof(floatFormat)=88
WARNING:  offsetof(blcksz)=96
WARNING:  offsetof(relseg)=100
WARNING:  offsetof(xlog)=104
WARNING:  offsetof(xlog)=108
WARNING:  offsetof(nameDataLen)=112
WARNING:  offsetof(indexMaxKeys)=116
WARNING:  offsetof(toast)=120
WARNING:  offsetof(enableIntTimes)=124
WARNING:  offsetof(localeBuflen)=128
WARNING:  offsetof(lc)=132
WARNING:  offsetof(lc)=260
WARNING:  offsetof(crc)=388
WARNING:  crc = 2265484434

Mingw:

WARNING:  sizeof(ControlFileData)=392
WARNING:  offsetof(state)=16
WARNING:  offsetof(time)=20
WARNING:  offsetof(checkPoint)=24
WARNING:  offsetof(prevCheckPoint)=32
WARNING:  offsetof(checkPointCopy)=40
WARNING:  offsetof(minRecoveryPoint)=76
WARNING:  offsetof(maxAlign)=84
WARNING:  offsetof(floatFormat)=88
WARNING:  offsetof(blcksz)=96
WARNING:  offsetof(relseg)=100
WARNING:  offsetof(xlog)=104
WARNING:  offsetof(xlog)=108
WARNING:  offsetof(nameDataLen)=112
WARNING:  offsetof(indexMaxKeys)=116
WARNING:  offsetof(toast)=120
WARNING:  offsetof(enableIntTimes)=124
WARNING:  offsetof(localeBuflen)=128
WARNING:  offsetof(lc)=132
WARNING:  offsetof(lc)=260
WARNING:  offsetof(crc)=388
WARNING:  crc = 3643130025

/D
Index: src/tools/msvc/Project.pm
===================================================================
RCS file: /projects/cvsroot/pgsql/src/tools/msvc/Project.pm,v
retrieving revision 1.14
diff -u -r1.14 src/tools/msvc/Project.pm
--- Project.pm    21 Aug 2007 15:10:41 -0000    1.14
+++ Project.pm    7 Dec 2007 11:14:29 -0000
@@ -489,7 +489,7 @@
     ConfigurationType="$cfgtype" UseOfMFC="0" ATLMinimizesCRunTimeLibraryUsage="FALSE" CharacterSet="2"
WholeProgramOptimization="$p->{wholeopt}">
     <Tool Name="VCCLCompilerTool" Optimization="$p->{opt}"

AdditionalIncludeDirectories="$self->{prefixincludes}src/include;src/include/port/win32;src/include/port/win32_msvc;$self->{includes}"
-
PreprocessorDefinitions="WIN32;_WINDOWS;__WINDOWS__;__WIN32__;EXEC_BACKEND;WIN32_STACK_RLIMIT=4194304;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE$self->{defines}$p->{defs}"
+
PreprocessorDefinitions="WIN32;_WINDOWS;__WINDOWS__;__WIN32__;EXEC_BACKEND;WIN32_STACK_RLIMIT=4194304;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;_USE_32BIT_TIME_T$self->{defines}$p->{defs}"
         StringPooling="$p->{strpool}"
         RuntimeLibrary="$p->{runtime}" DisableSpecificWarnings="$self->{disablewarnings}"

Re: Problem with ControlFileData structure being ABI dependent

From
Dave Page
Date:
Dave Page wrote:
> but the CRC is still different for some as-yet unknown reason...

Unknown because I wasn't fully grokking what it was a CRC of. Everything 
looks good now :-)

/D


Re: Problem with ControlFileData structure being ABI dependent

From
"Trevor Talbot"
Date:
On 12/7/07, Dave Page <dpage@postgresql.org> wrote:
> Tom Lane wrote:

> > AFAIK, time_t is a Unix-ism, so it's pretty unlikely to be used in the
> > APIs of anything on Windows.

> Oh, it is.

It's confined to the C Runtime libraries, not part of the Windows API
proper. (Three exceptions: IP Helper uses the type, but the docs
contain a warning; a DHCP API that came along after the change to
64bit; an obsoleted Wbem class library for C++.)

The CRT has been causing compatibility problems in mixed-tools
projects for years. I find Microsoft's incessant changes so irritating
that I go out of my way to avoid using it in any project I intend to
deploy. It's just one of those things you end up having to deal with
somehow :(