Skip to content

bpo-34373: Fix time.mktime() on AIX #12726

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Apr 9, 2019
Merged

bpo-34373: Fix time.mktime() on AIX #12726

merged 2 commits into from
Apr 9, 2019

Conversation

vstinner
Copy link
Member

@vstinner vstinner commented Apr 8, 2019

  • Fix time.mktime() on AIX: fix code checking for mktime() failure
    for years before 1970.
  • mktime(): rename variable 'buf' to 'tm'.
  • _PyTime_localtime(): avoid abs() which is limited to int type,
    use "localtime" rather than "ctime" in the error message.
  • _PyTime_localtime(): EINVAL constant is now always available.
  • _PyTime_localtime(): initialize errno to 0 just in case if
    localtime_r() doesn't set errno on error.

https://bugs.python.org/issue34373

@vstinner
Copy link
Member Author

vstinner commented Apr 8, 2019

cc @aixtools @ncoghlan

Fix time.mktime() error handling on AIX for year before 1970.

Other changes:

* mktime(): rename variable 'buf' to 'tm'.
* _PyTime_localtime():

  * Use "localtime" rather than "ctime" in the error message
    (specific to AIX).
  * Always initialize errno to 0 just in case if localtime_r()
    doesn't set errno on error.
  * On AIX, avoid abs() which is limited to int type.
  * EINVAL constant is now always available.
{
PyErr_SetString(PyExc_OverflowError,
"mktime argument out of range");
return NULL;
}

#ifdef _AIX
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The purpose of this chunk is unclear.
Probably need to comment how exactly AIX is faulty like in the others.

Copy link
Contributor

@aixtools aixtools Apr 8, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The issue AIX mktime() cannot handle on it's own - is that mktime() does not accept a tm structure when the value for tm_year is < 70.

The new version has an _AIX specific block before the call to mktime() (to add years to tm_year until it is >= 70 and remember this 'delta' in number of days per 4 years including leap-day.

Once adjusted (only when tm_year is < 70) the code is "normal". If mktime() fails, a failure is returned.

If mktime() was successful - and _AIX and delta_days != 0 then the structure adjusted by mktime() needs to be adjusted further (back in time):

  • the original year is restored
  • the tm_wday is adjusted according to delta_days
  • the number of seconds (tt) is adjusted according to delta_days.

Hope this helps.

@vstinner
Copy link
Member Author

vstinner commented Apr 9, 2019

@native-api: I added more comments. Is it better now?

@aixtools: Would you mind to review again my change please? (review the comments)

@vstinner
Copy link
Member Author

vstinner commented Apr 9, 2019

This change also fix this compiler warning:

./Modules/timemodule.c:999:13: warning: 'buf.tm_year' is used uninitialized in this function [-Wuninitialized]

https://buildbot.python.org/all/#/builders/10/builds/2358

@vstinner vstinner merged commit 8709490 into python:master Apr 9, 2019
@vstinner vstinner deleted the mktime_aix branch April 9, 2019 17:12
@native-api
Copy link
Contributor

Wow. So my word can actually influence something here.
Seeing the "awaiting core review" label, I thought it would be treated as a passing remark at best.
I'll put more thought into it from now on now that I see that others actually risk relying on it!

@vstinner
Copy link
Member Author

Don't worry. If anything goes wrong, it will be all my fault and I can handle it :-)

@EGuesnet
Copy link

Hi,
I have an error during regression tests with Python3.8.1 on AIX 6.1, and it seems related to this PR.
It occurs only on 64 bit. Test passes on 32 bit.

======================================================================
ERROR: test_add_file_after_2107 (test.test_zipfile.StoredTestsWithSourceFile)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/opt/freeware/src/packages/BUILD/Python-3.8.1/64bit/Lib/test/test_zipfile.py", line 606, in test_add_file_after_2107
    self.assertRaises(struct.error, zipfp.write, TESTFN)
  File "/opt/freeware/src/packages/BUILD/Python-3.8.1/64bit/Lib/unittest/case.py", line 816, in assertRaises
    return context.handle('assertRaises', args, kwargs)
  File "/opt/freeware/src/packages/BUILD/Python-3.8.1/64bit/Lib/unittest/case.py", line 202, in handle
    callable_obj(*args, **kwargs)
  File "/opt/freeware/src/packages/BUILD/Python-3.8.1/64bit/Lib/zipfile.py", line 1739, in write
    zinfo = ZipInfo.from_file(filename, arcname,
  File "/opt/freeware/src/packages/BUILD/Python-3.8.1/64bit/Lib/zipfile.py", line 523, in from_file
    mtime = time.localtime(st.st_mtime)
OverflowError: localtime argument out of range

Is the code 32 bit only, or maybe the test was not updated?


I can reproduce the behavior as follow:

$ python3.8_32
Python 3.8.1 (default, Jan 27 2020, 11:34:59) 
[GCC 8.3.0] on aix
Type "help", "copyright", "credits" or "license" for more information.
>>> import time
>>> time.localtime(4325562452)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
OverflowError: timestamp out of range for platform time_t

$ python3.8_64
Python 3.8.1 (default, Jan 27 2020, 11:30:15) 
[GCC 8.3.0] on aix
Type "help", "copyright", "credits" or "license" for more information.
>>> import time
>>> time.localtime(4325562452)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
OverflowError: localtime argument out of range

$ python3.7_32
Python 3.7.4 (default, Jan 15 2020, 15:50:53) 
[GCC 8.3.0] on aix6
Type "help", "copyright", "credits" or "license" for more information.
>>> import time
>>> time.localtime(4325562452)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
OverflowError: timestamp out of range for platform time_t

$ python3.7_64
Python 3.7.4 (default, Jan 15 2020, 15:46:22) 
[GCC 8.3.0] on aix6
Type "help", "copyright", "credits" or "license" for more information.
>>> import time
>>> time.localtime(4325562452)
time.struct_time(tm_year=2107, tm_mon=1, tm_mday=27, tm_hour=10, tm_min=7, tm_sec=32, tm_wday=3, tm_yday=27, tm_isdst=0)

Before the PR, localtime after 2038 worked on 64 bit.

@aixtools
Copy link
Contributor

aixtools commented Jan 30, 2020 via email

@vstinner
Copy link
Member Author

I have an error during regression tests with Python3.8.1 on AIX 6.1

This PR is closed. Please open a new issue at https://bugs.python.org/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants