Use _mkgmtime64 instead of _mktime64 to implement Windows Unix.stat#861
Use _mkgmtime64 instead of _mktime64 to implement Windows Unix.stat#861nojb wants to merge 1 commit intoocaml:trunkfrom
Conversation
|
(I don't understand the details so apologies if this is a silly question, but) The MSDN documentation indicates that the |
|
It should not happen with the proposed workaround, since we would not be doing any timezone conversion. |
|
We are running OCaml under |
|
This looks good to me. @dra27 Do you have an opinion on this topic? |
|
I need more time to be able to look at this properly - I've got a feeling that the implementation I did was designed for compatibility with the Microsoft C implementation (the code for that is available in any paid for distro of Visual Studio prior to 2015 and in all 2015 distros). I think the idea was that I only enhanced fields (so some fields are populated, such as |
|
An update on this issue: this patch does not compile on |
|
I think that fixing for the MSVC ports would already be useful, even if having a different behavior between MSVC and Mingw is not great. |
|
OK, I will add the necessary preprocessor macros and update the patch. |
|
OK, sorry for the long delay on my input here. I have no idea how this slipped through when I developed stat - perhaps it was a combination of my working in a VM (which has a habit of resetting the system clock to the host) or that I developed this while in the Netherlands and got confused from my usual lazy comfort of living in UTC+0! So, what is wrong with the code is the use of the wrong API function - it's step 2 which is the problem. The correct sequence - noted in MSDN (brief blush for not reading the docs properly...) is --- a/otherlibs/win32unix/stat.c
+++ b/otherlibs/win32unix/stat.c
@@ -118,11 +119,11 @@ static value stat_aux(int use_64, __int64 st_ino, struct _stat64 *buf)
static int convert_time(FILETIME* time, __time64_t* result, __time64_t def)
{
SYSTEMTIME sys;
- FILETIME local;
+ SYSTEMTIME local;
if (time->dwLowDateTime || time->dwHighDateTime) {
- if (!FileTimeToLocalFileTime(time, &local) ||
- !FileTimeToSystemTime(&local, &sys))
+ if (!FileTimeToSystemTime(time, &sys) ||
+ !SystemTimeToTzSpecificLocalTime(NULL, &sys, &local))
{
win32_maperr(GetLastError());
return 0;The issue with mingw32 is because it only permits the binary API of Visual Studio 6.0 (the full and reasonable explanation is here). It does this with good reason - _mkgmtime64 is not available in msvcrt.dll until Windows Vista. I'm not convinced that this single issue is a good enough reason to drop Windows 2000 and Windows XP completely. Using My feeling is that both versions should go in - the additional safety offered by I've proposed #1057 for this. |
25188da flambda-backend: Missed comment from PR802 (ocaml#887) 9469765 flambda-backend: Improve the semantics of asynchronous exceptions (new simpler version) (ocaml#802) d9e4dd0 flambda-backend: Fix `make runtest` on NixOS (ocaml#874) 4bbde7a flambda-backend: Simpler symbols (ocaml#753) ef37262 flambda-backend: Add opaqueness to Obj.magic under Flambda 2 (ocaml#862) a9616e9 flambda-backend: Add build system hooks for ocaml-jst (ocaml#869) 045ef67 flambda-backend: Allow the compiler to build with stock Dune (ocaml#868) 3cac5be flambda-backend: Simplify Makefile logic for natdynlinkops (ocaml#866) c5b12bf flambda-backend: Remove unnecessary install lines (ocaml#860) ff12bbe flambda-backend: Fix unused variable warning in st_stubs.c (ocaml#861) c84976c flambda-backend: Static check for noalloc: attributes (ocaml#825) ca56052 flambda-backend: Build system refactoring for ocaml-jst (ocaml#857) 39eb7f9 flambda-backend: Remove integer comparison involving nonconstant polymorphic variants (ocaml#854) c102688 flambda-backend: Fix soundness bug by using currying information from typing (ocaml#850) 6a96b61 flambda-backend: Add a primitive to enable/disable the tick thread (ocaml#852) f64370b flambda-backend: Make Obj.dup use a new primitive, %obj_dup (ocaml#843) 9b78eb2 flambda-backend: Add test for ocaml#820 (include functor soundness bug) (ocaml#841) 8f24346 flambda-backend: Add `-dtimings-precision` flag (ocaml#833) 65c2f22 flambda-backend: Add test for ocaml#829 (ocaml#831) 7b27a49 flambda-backend: Follow-up PR#829 (comballoc fixes for locals) (ocaml#830) ad7ec10 flambda-backend: Use a custom condition variable implementation (ocaml#787) 3ee650c flambda-backend: Fix soundness bug in include functor (ocaml#820) 2f57378 flambda-backend: Static check noalloc (ocaml#778) aaad625 flambda-backend: Emit begin/end region only when stack allocation is enabled (ocaml#812) 17c7173 flambda-backend: Fix .cmt for included signatures (ocaml#803) e119669 flambda-backend: Increase delays in tests/lib-threads/beat.ml (ocaml#800) ccc356d flambda-backend: Prevent dynamic loading of the same .cmxs twice in private mode, etc. (ocaml#784) 14eb572 flambda-backend: Make local extension point equivalent to local_ expression (ocaml#790) 487d11b flambda-backend: Fix tast_iterator and tast_mapper for include functor. (ocaml#795) a50a818 flambda-backend: Reduce closure allocation in List (ocaml#792) 96c9c60 flambda-backend: Merge ocaml-jst a775b88 flambda-backend: Fix ocaml/otherlibs/unix 32-bit build (ocaml#767) f7c2679 flambda-backend: Create object files internally to avoid invoking GAS (ocaml#757) c7a46bb flambda-backend: Bugfix for Cmmgen.expr_size with locals (ocaml#756) b337cb6 flambda-backend: Fix build_upstream for PR749 (ocaml#750) 8e7e81c flambda-backend: Differentiate is_int primitive between generic and variant-only versions (ocaml#749) git-subtree-dir: ocaml git-subtree-split: 25188da
* package layout header contains breadcrumbs now --------- Co-authored-by: Sabine Schmaltz <[email protected]>
(Continued from Mantis MPR #7835)
The problem
Unix.staton Windows returns time stamps which depend on the DST setting of the computer.How to reproduce
Given an existing file
FILE, simply dothen change your Windows DST setting and retry. The resulting timestamps should have changed by
3600.(1 hour).Some information learned so far
Windows
Unix.stattime stamps are currently computed as follows:FILETIME, a 64bit value)FileTimeToLocalFileTime)SYSTEMTIME, similar totmstructure, usingFileTimeToSystemTime)tmstructure "by hand"_mktime64(takes atmstructure in local time zone)It looks like the problematic step is 4. -> 5. Indeed, the
tmstructure has a fieldtm_isdst, supposed to be set to0,1, or-1according to whether DST is inactive, active, or should be taken from the OS. Since the output ofFileTimeToLocalFileTimetakes the DST setting from the OS, one should probably set this field to-1to compensate (incidentally, this field is always set to-1in the Un*x implementation ofUnix.mktime).Currently, this field is set to
0instead. So I hoped this was the culprit. However, passing-1does not seem to have any effect. This behavior is still a mystery.Also relevant:
Proposed solution
Sidestepping the conversion to local time by using the Windows function
_mkgmtime64. This is an avatar of the non-standard GNU C functiontimegm. The resulting time stamps seem to be correct and invariant under DST changes.While this change seems to solve the issue, the source of the problem is not yet fully understood. Any comments on the problem and/or the solution, as well as confirmation of the problem would be greatly appreciated!