Skip to content

Name the Parmlib member that is actually in effect - #168

Merged
mgrossmann merged 1 commit into
mainfrom
issue-166-name-the-parmlib-member
Aug 10, 2026
Merged

Name the Parmlib member that is actually in effect#168
mgrossmann merged 1 commit into
mainfrom
issue-166-name-the-parmlib-member

Conversation

@mgrossmann

Copy link
Copy Markdown
Contributor

Fixes #166

The defect

httpd.c:95 printed the CONFIG= parm, which http_config() has ignored since
the Parmlib migration ((void)member) — and which the shipped STC procedure
does not pass at all. So the one message naming what failed to process always
read:

HTTPD404E Errors occured processing (null)

After #163 and #165 gave the parser real reasons to refuse a startup, that
message became a lot more visible.

Name the member instead

The configuration's real identity is the HTTPPRM DD, and the PROC allocates it
as &D(&M) — so S HTTPD and S HTTPD,M=HTTPPRM1 read different members and
"which one is this server running?" is a question an operator can genuinely
have. Nothing answered it before.

parmlib_name() resolves it from DSAB → TIOT entry → JFCB (get_dsab(),
TIOEJFCB, jfcbdsnm + jfcbelnm) — read-only pointer chasing, no SVC and no
allocation, the same walk __listal() does. It falls back to the DD name if any
link is missing, so a caller always gets something printable. __listal() itself
was not reusable: it drops jfcbelnm, which is the half that matters here.

It is reported before parsing, so a later error is already attributed:

HTTPD022I Configuration from SYS2.PARMLIB(HTTPPRM0)

and HTTPD404E drops the operand.

CONFIG= is answered rather than swallowed

The issue asks whether to remove it or make it select the member. Neither:

  • S HTTPD,M=member already is the MVS-native way to select one, so a second
    mechanism would be redundant.
  • Removing the parse leaves a leftover parm as silently ineffective as it is
    today, which is the actual problem — an operator who passes it believes it took
    effect. migration.md still tells 3.x users to remove PARM='CONFIG=...' from
    their JCL, so a leftover is exactly what this catches.

HTTPD024W now says it did nothing and names the mechanism that does.

Testing

All three halves are directly observable, so all three were observed on the live
system rather than argued for.

1. The member is resolved, and it is the real one — not the fallback and not a
default.
Started twice, with different members:

HTTPD022I Configuration from SYS2.PARMLIB(HTTPPRM0)     S HTTPD
HTTPD022I Configuration from SYS2.PARMLIB(HTTPPRM9)     S HTTPD,M=HTTPPRM9

The second is what proves the JFCB walk reads the live allocation.

2. The failure path now attributes itself. Started on a member carrying the
malformed route from #164, so the whole chain is visible at once:

HTTPD022I Configuration from SYS2.PARMLIB(HTTPPRM9)
HTTPD415W LOC= requires a path (e.g. LOC /admin/* AUTH=BASIC)
HTTPD419E LOC=AUTH=BASIC RES=FACILITY:HTTPD.ADMIN could not be registered -- its auth policy is lost
HTTPD420E Route authorization policy incomplete -- HTTPD will not start
HTTPD404E Errors occured processing the configuration

Which member, what was wrong with it, why that is fatal, and that startup ended
— previously the first and last lines were "nothing" and "(null)".

3. CONFIG= is caught. The STC procedure passes no PARM — which is why the
old message could only ever print "(null)" — so this needed a batch run, pointed
at the same bad member so it terminates at once and never competes for the port:

//RUN      EXEC PGM=HTTPD,REGION=8M,PARM='CONFIG=MY.OLD.LUA(HTTPD)'
//HTTPPRM  DD  DSN=SYS2.PARMLIB(HTTPPRM9),DISP=SHR
HTTPD024W CONFIG=MY.OLD.LUA(HTTPD) is ignored; the configuration comes from the HTTPPRM DD
HTTPD024W Use S HTTPD,M=member to select a different member
HTTPD022I Configuration from SYS2.PARMLIB(HTTPPRM9)

That run also confirms the JFCB walk works against a batch DD, not just the
STC's.

Temporary member deleted, server restarted on HTTPPRM0, /.dsrv and
/zosmf/restfiles both 200, production member verified byte-for-byte unchanged.
Also make modules / make test clean under -Wall -Werror, make test-host
4 suites / 63 assertions / 0 fail.

Docs

configuration.md gains the member-selection note and the HTTPD022I line;
migration.md shows what a leftover PARM='CONFIG=...' now produces, next to
the instruction to remove it.

HTTPD404E printed the CONFIG= parm, which http_config() has ignored
since the Parmlib migration -- and which the shipped STC procedure
does not pass at all, so the one message naming what failed to process
always read "processing (null)". After #163 and #165 gave the parser
real reasons to refuse a startup, that message got a lot more
visible.

The configuration's real identity is the HTTPPRM DD, and the PROC
allocates it as &D(&M), so which member is in effect is a startup
choice an operator can genuinely need to confirm. parmlib_name()
resolves it from the DSAB -> TIOT entry -> JFCB, read-only pointer
chasing with no SVC and no allocation, falling back to the DD name if
any link is missing. It is reported before parsing, so a later error
is already attributed:

    HTTPD022I Configuration from SYS2.PARMLIB(HTTPPRM0)

HTTPD404E drops the operand accordingly.

CONFIG= is now answered rather than swallowed. Silently ignoring it is
worse than not accepting it -- an operator who passes it believes it
took effect, and migration.md still tells 3.x users to remove theirs,
so a leftover is exactly what this catches. HTTPD024W says it did
nothing and names the mechanism that does.

Fixes #166
@mgrossmann
mgrossmann merged commit 3e612fe into main Aug 10, 2026
1 check passed
@mgrossmann
mgrossmann deleted the issue-166-name-the-parmlib-member branch August 10, 2026 05:17
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.

HTTPD404E names the ignored CONFIG= parm, so every fatal config error ends with "processing (null)"

1 participant