Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit dd53b46

Browse filesBrowse files
committed
Work around portability issue with newer versions of mktime().
Recent glibc versions have made mktime() fail if tm_isdst is inconsistent with the prevailing timezone; in particular it fails for tm_isdst = 1 when the zone is UTC. (This seems wildly inconsistent with the POSIX-mandated treatment of "incorrect" values for the other fields of struct tm, so if you ask me it's a bug, but I bet they'll say it's intentional.) This has been observed to cause cosmetic problems when pg_restore'ing an archive created in a different timezone. To fix, do mktime() using the field values from the archive, and if that fails try again with tm_isdst = -1. This will give a result that's off by the UTC-offset difference from the original zone, but that was true before, too. It's not terribly critical since we don't do anything with the result except possibly print it. (Someday we should flush this entire bit of logic and record a standard-format timestamp in the archive instead. That's not okay for a back-patched bug fix, though.) Also, guard our only other use of mktime() by having initdb's build_time_t() set tm_isdst = -1 not 0. This case could only have an issue in zones that are DST year-round; but I think some do exist, or could in future. Per report from Wells Oliver. Back-patch to all supported versions, since any of them might need to run with a newer glibc. Discussion: https://postgr.es/m/CAOC+FBWDhDHO7G-i1_n_hjRzCnUeFO+H-Czi1y10mFhRWpBrew@mail.gmail.com
1 parent 84cb4be commit dd53b46
Copy full SHA for dd53b46

File tree

Expand file treeCollapse file tree

2 files changed

+28
-5
lines changed
Filter options
Expand file treeCollapse file tree

2 files changed

+28
-5
lines changed

‎src/bin/initdb/findtimezone.c

Copy file name to clipboardExpand all lines: src/bin/initdb/findtimezone.c
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,7 @@ build_time_t(int year, int month, int day)
195195
tm.tm_mday = day;
196196
tm.tm_mon = month - 1;
197197
tm.tm_year = year - 1900;
198+
tm.tm_isdst = -1;
198199

199200
return mktime(&tm);
200201
}

‎src/bin/pg_dump/pg_backup_archiver.c

Copy file name to clipboardExpand all lines: src/bin/pg_dump/pg_backup_archiver.c
+27-5Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3615,7 +3615,6 @@ void
36153615
ReadHead(ArchiveHandle *AH)
36163616
{
36173617
int fmt;
3618-
struct tm crtm;
36193618

36203619
/*
36213620
* If we haven't already read the header, do so.
@@ -3683,6 +3682,8 @@ ReadHead(ArchiveHandle *AH)
36833682

36843683
if (AH->version >= K_VERS_1_4)
36853684
{
3685+
struct tm crtm;
3686+
36863687
crtm.tm_sec = ReadInt(AH);
36873688
crtm.tm_min = ReadInt(AH);
36883689
crtm.tm_hour = ReadInt(AH);
@@ -3691,12 +3692,33 @@ ReadHead(ArchiveHandle *AH)
36913692
crtm.tm_year = ReadInt(AH);
36923693
crtm.tm_isdst = ReadInt(AH);
36933694

3694-
AH->archdbname = ReadStr(AH);
3695-
3695+
/*
3696+
* Newer versions of glibc have mktime() report failure if tm_isdst is
3697+
* inconsistent with the prevailing timezone, e.g. tm_isdst = 1 when
3698+
* TZ=UTC. This is problematic when restoring an archive under a
3699+
* different timezone setting. If we get a failure, try again with
3700+
* tm_isdst set to -1 ("don't know").
3701+
*
3702+
* XXX with or without this hack, we reconstruct createDate
3703+
* incorrectly when the prevailing timezone is different from
3704+
* pg_dump's. Next time we bump the archive version, we should flush
3705+
* this representation and store a plain seconds-since-the-Epoch
3706+
* timestamp instead.
3707+
*/
36963708
AH->createDate = mktime(&crtm);
3697-
36983709
if (AH->createDate == (time_t) -1)
3699-
write_msg(modulename, "WARNING: invalid creation date in header\n");
3710+
{
3711+
crtm.tm_isdst = -1;
3712+
AH->createDate = mktime(&crtm);
3713+
if (AH->createDate == (time_t) -1)
3714+
write_msg(modulename,
3715+
"WARNING: invalid creation date in header\n");
3716+
}
3717+
}
3718+
3719+
if (AH->version >= K_VERS_1_4)
3720+
{
3721+
AH->archdbname = ReadStr(AH);
37003722
}
37013723

37023724
if (AH->version >= K_VERS_1_10)

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.