Thread: Problem with ControlFileData structure being ABI dependent
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!
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
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
"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!
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
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
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}"
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
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 :(