Default TZOFFSET to the offset libc370 already resolved - #150
Conversation
httpd carried a second, disagreeing notion of the timezone. httpd->tzoffset fed the Date: header, the SMF timestamps and DISPLAY TIME, while everything that went through localtime()/ctime64() -- modules, worker threads, dbgtime.c -- used crt->crttzoff. The two had unrelated defaults: 0 for the former, the system's CVTTZ for the latter, filled in per task by @@crtset.c and refreshed by the tzset() that both __start paths already call. On the reference system CVTTZ is -5h, so with an empty Parmlib the server reported its own local time as equal to GMT while the same event was stamped five hours earlier by MVS and by every module. Nothing was configured; the 0 was not a chosen default but an untouched field in static storage, which is also why it read as "GMT" in the HTTPD block and misled the first analysis of issue #145. set_defaults() now takes __tzget(), i.e. crt->crttzoff as tzset() left it -- the TZ environment variable when a SYSENV/ENVIRON DD sets one, the system's CVTTZ otherwise. Both halves then agree with each other and with MVS. A TZOFFSET statement still wins, because http_config() runs set_defaults() before it parses the member. Documentation said the default was +00:00, which described the bug rather than an intent; it now says the offset comes from the system unless the Parmlib overrides it. Not covered by a test: the value comes from the task's CRT, so there is nothing a host test can exercise. Verify with F HTTPD,DISPLAY TIME -- GMT and Local should differ by the system offset instead of being equal -- and by comparing start_stamp against start_display in /jes/status. This is part (a) of #145. Part (b) -- that an explicit TZOFFSET still reaches only the task that parsed the Parmlib, while TZ in the SYSENV DD reaches all of them -- is a policy decision and stays open. Refs #145
Verified on MVS — and this PR does more than its description claims
The default now matches the system, and an explicit statement still wins. The part I had not predicted: this also fixes the JES2 epoch timestampsReading JES2 stores system local time, so the epoch is only correct when
So, for a job started at 12:08:57 local on a system running at UTC−5 (true UTC 17:08:57):
Before this change the JES2 epoch timestamps were systematically wrong by the system offset, on every system whose CVTTZ is not zero. That is a correctness fix, not just an alignment of httpd's own formatting, and the PR title and body both undersell it. Every input above is measured. The one step not read directly is It also reshapes part (b) of #145I asked there whether |
Part (a) of #145. One line plus a comment; part (b) stays open as a policy decision.
The problem
httpd carried a second, disagreeing notion of the timezone:
httpd->tzoffsetTZOFFSETDate:header, SMF timestamps,DISPLAY TIMEcrt->crttzoff@@crtset.cper task fromCVTTZ; refreshed by thetzset()both__startpaths already calllocaltime()/ctime64()→ modules, worker threads,dbgtime.cTwo unrelated defaults for the same question, in one address space. With
SYS2.PARMLIB(HTTPPRM0)setting nothing:The server calls 16:39 its local time; MVS stamps the same event 11:39, and so does every module (
/jes/statusrendersstart_displayfive hours behindstart_stamp).The
0was never a chosen default. The HTTPD block is static storage,set_defaults()did not touch the field, andparse_tzoffset()— its only writer — runs only for an actualTZOFFSETstatement. That is also what misled the first analysis on #145: reading an untouched field as "configured for GMT".The change
__tzget()returnscrt->crttzoffastzset()left it: theTZenvironment variable when the STC allocates a SYSENV/ENVIRON DD that sets one, the system'sCVTTZotherwise. Both halves then agree with each other and with MVS.An explicit
TZOFFSETstill wins —http_config()callsset_defaults()before it parses the member, andparse_tzoffset()overwrites the value.__tzget()is declared locally, likesleep()and__tzset()above it: libc370 ships it (src/clib/@@tzget.c) but declares it in no header (mvslovers/libc370#70).Documentation
docs/configuration.mdgave the default as+00:00, which documented the bug rather than an intention. It now says the offset comes from the system unless the Parmlib overrides it, and names where the system value comes from.Verification
makeclean under-Wall -Werror, 6 modules link,make test-host63 assertions pass.No test covers this. The value comes from the calling task's CRT, so there is nothing a host test can exercise and nothing an MVS test can assert without a known CVTTZ. It has to be checked on the live system:
F HTTPD,DISPLAY TIME—HTTPD142I(GMT) andHTTPD143I(Local) should now differ by the system offset instead of being equal, andTZOFFSET=should report it./jes/status?jobname=…—start_displayshould matchstart_stampinterpreted at that same offset.TZOFFSETin the Parmlib should still override both.I would rather that ran before this merges, since the whole change is about a value only the live system produces.
What stays open
Part (b) of #145: an explicit
TZOFFSETstill reaches only the task that parsed the Parmlib, becauseparse_tzoffset()→__tzset()writes that task's CRT. Worker threads and modules keep theirs. The libc370-sanctioned way to reach all of them already exists —TZin the SYSENV/ENVIRON DD, honoured bytzset()in bothhttpstrt.candcgistart.c— which raises the question whether the Parmlib keyword should do anything beyond feeding httpd's own formatting. That is a decision, not a defect, and it is not in this PR.