This issue tracker has been migrated to GitHub ,
and is currently read-only.
For more information,
see the GitHub FAQs in the Python's Developer Guide.
Created on 2015年11月02日 15:35 by Sean.Wang, last changed 2022年04月11日 14:58 by admin.
| Files | ||||
|---|---|---|---|---|
| File name | Uploaded | Description | Edit | |
| test | Sean.Wang, 2015年11月02日 15:38 | strange last modified date | ||
| Messages (8) | |||
|---|---|---|---|
| msg253926 - (view) | Author: Sean Wang (Sean.Wang) | Date: 2015年11月02日 15:35 | |
I transfered a file from remote Debian host to my local Windows 10 host using SecureFX.
I found that the file's last modifed date was 1900/1/1,0:00:00 on Windows.
I tried to serve this file to be downloaded, and it crashed as follows:
Exception happened during processing of request from ('192.168.1.102', 50978)
Traceback (most recent call last):
File "C:\Python27\lib\SocketServer.py", line 295, in _handle_request_noblock
self.process_request(request, client_address)
File "C:\Python27\lib\SocketServer.py", line 321, in process_request
self.finish_request(request, client_address)
File "C:\Python27\lib\SocketServer.py", line 334, in finish_request
self.RequestHandlerClass(request, client_address, self)
File "C:\Python27\lib\SocketServer.py", line 655, in __init__
self.handle()
File "C:\Python27\lib\BaseHTTPServer.py", line 340, in handle
self.handle_one_request()
File "C:\Python27\lib\BaseHTTPServer.py", line 328, in handle_one_request
method()
File "C:\Python27\lib\SimpleHTTPServer.py", line 45, in do_GET
f = self.send_head()
File "C:\Python27\lib\SimpleHTTPServer.py", line 103, in send_head
self.send_header("Last-Modified", self.date_time_string(fs.st_mtime))
File "C:\Python27\lib\BaseHTTPServer.py", line 468, in date_time_string
year, month, day, hh, mm, ss, wd, y, z = time.gmtime(timestamp)
ValueError: (22, 'Invalid argument')
I have checked the source code, and found it was because of the last modifed date of the file, I got this in console:
>>> os.fstat(f.fileno())
nt.stat_result(st_mode=33206, st_ino=4785074604093500L, st_dev=0L, st_nlink=1, st_uid=0, st_gid=0, st_size=3406L, st_atime=1446477520L, st_mtime=-2209017600L, st_ctime=1446370767L)
-2209017600L cannot be handled by "time.gmtime()" method and it throwed
error
|
|||
| msg253927 - (view) | Author: Sean Wang (Sean.Wang) | Date: 2015年11月02日 15:38 | |
upload a sample test file |
|||
| msg253948 - (view) | Author: Martin Panter (martin.panter) * (Python committer) | Date: 2015年11月02日 22:37 | |
I think your test file’s time is lost on the web server. On Linux it is pretty easy to make a file with an arbitrary time; maybe Windows has an equivalent: $ touch -d "1 Jan 1900" test I experimented with Wine, and it seems gmtime() raises ValueError on Python 2 and OSError on Python 3 for negative times, but under Linux negative times are handled successfully. (Wine seems to wrap the st_mtime field to a 32-bit unsigned value though, so I am unable to reproduce the original problem.) The "time" module documentation says "The functions in this module may not handle dates and times before the epoch", so maybe the HTTP module should be fixed to handle a ValueError (or OSError on Python 3). |
|||
| msg254081 - (view) | Author: Xiang Zhang (xiang.zhang) * (Python committer) | Date: 2015年11月05日 03:59 | |
I'm afraid we can't say negative epoch is handled successfully on Linux. Use $ touch -d "1 Jan 1900" test as a test, time.gmtime(os.fstat(f.fileno()).st_mtime) gives time.struct_time(tm_year=1899, tm_mon=12, tm_mday=31, tm_hour=15, tm_min=54, tm_sec=17, tm_wday=6, tm_yday=365, tm_isdst=0), which does not equals "1 Jan 1900". I think this is caused by python gmtime directly uses gmtime in C. Use the epoch of "1 Jan 1900" with C's gmtime does not give a right result. And while I am searching, I can not find any evidence that gmtime in C can give a right result with a negtive epoch. And when I try the epoch of "1 Jan 1900" with "date -d @", it can generate the right result. |
|||
| msg254082 - (view) | Author: Martin Panter (martin.panter) * (Python committer) | Date: 2015年11月05日 04:15 | |
Perhaps you have a timezone set (I don’t). This might work better: touch -d "1 Jan 1900 UTC" test My thinking is if os.stat() returns a negative timestamp from the OS (GNU C library in the case of Linux), it may be worth trying gmtime() on that value since it also calls the OS (glibc) function. |
|||
| msg254083 - (view) | Author: Xiang Zhang (xiang.zhang) * (Python committer) | Date: 2015年11月05日 04:44 | |
You're right. Actually I do think of timezone when I do the experiment. But I think different timezone will only affect the hour. It turns out I should learn more about time. |
|||
| msg254246 - (view) | Author: Terry J. Reedy (terry.reedy) * (Python committer) | Date: 2015年11月07日 00:50 | |
Does this affect 3.x also? I would expect that it does. The question for this issue is whether the program should stop on a gmtime error and say "I will not serve this file until you fix the modification time." or whether it should catch and workaround the problem and merely warn about the mtime. For the latter, BaseHTTPServer could catch the gmtime error and use the current time instead. Or SimpleHTTPServer could catch the exception and omit the Last Modified: header, if that is allowed. I believe the purpose of this header is for caching, and the current time would say to replace any cached value. |
|||
| msg254249 - (view) | Author: Martin Panter (martin.panter) * (Python committer) | Date: 2015年11月07日 01:41 | |
I assume it affects Python 3, though I suspect the exception is OSError, not ValueError. But it would be good if someone with Windows (or other affected OS) could confirm. I think the server should serve the file, with just a best-effort attempt to serve the timestamp. Some other options: * Maybe using datetime rather than the OS’s gmtime() would be more reliable * Omit the Last-Modified header if the timestamp cannot be represented * Make time.gmtime() more platform-independent (probably against the original spirit of the module) I don’t think setting Last-Modified to the current time is a particularly good idea. I guess omitting the field would have a similar effect on caching, without actually serving a misleading value. |
|||
| History | |||
|---|---|---|---|
| Date | User | Action | Args |
| 2022年04月11日 14:58:23 | admin | set | github: 69720 |
| 2015年11月07日 01:41:26 | martin.panter | set | messages:
+ msg254249 versions: + Python 3.4, Python 3.5, Python 3.6 |
| 2015年11月07日 00:50:51 | terry.reedy | set | nosy:
+ terry.reedy messages: + msg254246 |
| 2015年11月05日 04:44:05 | xiang.zhang | set | messages: + msg254083 |
| 2015年11月05日 04:15:11 | martin.panter | set | messages: + msg254082 |
| 2015年11月05日 03:59:18 | xiang.zhang | set | nosy:
+ xiang.zhang messages: + msg254081 |
| 2015年11月02日 22:38:00 | martin.panter | set | nosy:
+ paul.moore, tim.golden, martin.panter, zach.ware, steve.dower messages: + msg253948 components: + Windows type: crash -> behavior stage: needs patch |
| 2015年11月02日 15:38:20 | Sean.Wang | set | files:
+ test messages: + msg253927 |
| 2015年11月02日 15:35:17 | Sean.Wang | create | |