Chapter 4. The Started Task and the Package
HTTPD runs as a started task. This chapter lists the procedure that ships with HTTPD and every DD name in it. It then shows how the server gets its authorization and its identity, which calls it makes to the security product, the order of the start, and the return codes of the job step. The last part is a map of the package: the FMID, the data sets and the members.
The HTTPD User’s Guide shows how to install the package and how to run the task, in “Installing HTTPD” and “Operating HTTPD”.
The Procedure
The member HTTPD of the sample library is the procedure. The operator copies it to the procedure library, for example to SYS2.PROCLIB(HTTPD). This is the member without its comment lines.
//HTTPD PROC M=HTTPPRM0,
// D='SYS2.PARMLIB',
// STCUSER=HTTPD,
// STCGRP=USER
//HTTPD EXEC PGM=HTTPD,REGION=8M,TIME=1440,
// PARM='STCUSER=&STCUSER STCGROUP=&STCGRP'
//STEPLIB DD DISP=SHR,DSN=HTTPD.LINKLIB
//SYSUDUMP DD SYSOUT=*
//HTTPDERR DD SYSOUT=*
//HTTPDOUT DD SYSOUT=*
//HTTPDIN DD DUMMY
//SNAP DD SYSOUT=*
//HTTPDBG DD SYSOUT=*
//HTTPSTAT DD SYSOUT=*
//HTTPPRM DD DSN=&D(&M),DISP=SHR,FREE=CLOSEThe member also has the statements HASPCKPT and HASPACE1, as comment lines (“The JES2 data sets”).
The package build writes the name of the library that SMP installs into, here HTTPD.LINKLIB, into the STEPLIB statement of the member.
The symbolic parameters
| Symbolic | Default | Meaning |
M | HTTPPRM0 | The member of the Parmlib. It is the member name in the HTTPPRM DD. |
D | SYS2.PARMLIB | The data set that holds the member. |
STCUSER | HTTPD | The user id that the server takes as its identity (“The Identity of the Task”). |
STCGRP | USER | The group of that user id. The name is STCGRP and not STCGROUP, because the name of a JCL symbolic parameter has at most 7 characters. The PARM keyword that the program reads is STCGROUP=. |
Table 25. The symbolic parameters of the procedure
The START command overrides a symbolic:
S HTTPD
S HTTPD,M=HTTPPRM1
S HTTPD,D='MY.PARMLIB'
S HTTPD,STCUSER=WEBSRV,STCGRP=WEBGRPThe EXEC statement
The program is HTTPD. The procedure sets REGION=8M and TIME=1440. The server reads its arguments from the PARM string. It splits the string at blanks and not at commas. It knows these keywords.
| Keyword | Meaning |
STCUSER=name | The user id for the identity of the task. The default is HTTPD. A keyword without a value gives the default. |
STCGROUP=name | The group for the identity. The default is USER. A keyword without a value gives the default. |
CONFIG=name | Has no effect. HTTPD writes HTTPD024W CONFIG=name IS IGNORED, CONFIGURATION COMES FROM THE HTTPPRM DD and then HTTPD024I USE S HTTPD,M=MEMBER TO SELECT A DIFFERENT MEMBER. The symbolic M selects the member. |
Table 26. The PARM keywords
HTTPD ignores any other word in the PARM string, without a message. The configuration of the server comes from the Parmlib member and not from the PARM string. Chapter 1, “The HTTPPRM Keywords” lists the keywords of the member.
The region
The REGION of the EXEC statement is the one limit on all the storage that the server holds. It is not a Parmlib keyword. A server that runs many module requests at the same time may need more than the 8M of the shipped procedure.
Every request that runs a module takes one contiguous block of storage for the C stack of the module, from the region, for as long as the module runs.
| What | Size |
| C stack of a module that sets nothing | 262,328 bytes, about 256 KB. It is the default of the C runtime (@@CRT0 of LIBC/370). A module that sets __stklen gets that size (“What the Startup Code Does”). |
C stack of a module with its own __stklen | The value plus 48 bytes. mvsMF sets 64 KB, so a request of mvsMF takes 65,584 bytes. |
| Stack of a worker thread | 64 KB, once per worker thread. |
| Stack of the socket thread | 32 KB, once. |
| Resident copy of a module | The size of the load module, once per module and not per request (RESIDENT, “Routes and Modules”). |
Table 27. What a module request costs
A request runs on a worker thread, so at most MAXTASK module requests run at once, and their stacks add up to MAXTASK times the stack of the module. At the default MAXTASK=9 and modules with the default stack that is 9 times 262,328 = 2,360,952 bytes, plus 9 times 64 KB for the worker threads. The stack is one contiguous block, so the free storage of the region has to be whole enough to hold it and not only large enough in sum. Each step of MAXTASK costs at least one more worker stack and one more module stack, before the working storage of the module itself.
If the request cannot get its stack, the module does not start. The console shows
@@CRT0 - No storage for C stack HTTPD908E EXTERNAL PROGRAM REXX failed with U0801 ABEND
and the client gets status 503 with the text External program REXX failed. The other requests of the server go on. A module that is linked against a LIBC/370 older than 1.0.3 does not ask for the stack with a condition and abends
with U0801 ABENDS80A instead, from inside the system. HTTPD904E and HTTPD999E are the same shortage in the storage of the server itself.
Only a measurement shows the size that a site needs. This one was made against a release candidate of 4.4.0: 60 requests to REXX pages, 9 at a time. The table gives the failed requests of the 60, one entry per run.
| Set-up | Failed requests of 60 |
REGION=8M, RESIDENT=YES | 6, 32, 0 |
REGION=8M, HTTPD 4.3.0 with the same module libraries | 0, 4, 0 |
REGION=8M, RESIDENT=NO | 0 (one run) |
REGION=16M | 0 (one run) |
Table 28. A measurement of parallel module requests
A mixed load of 6 requests at a time across all module types was clean in every set-up. The sample is small and the runs are not independent. It shows an order of magnitude and not a threshold. It was not run with Lua requests. Three rules follow from it.
- For many parallel REXX or Lua requests, set
REGION=16Min the procedure before you raiseMAXTASK. 16M is the largest value that was tried. If it is not enough, lowerMAXTASKand do not raise it. - Raise
MAXTASKonly together with the region. - Do not use
RESIDENT=NOas the cure. It brings back the fetch of the module on every request.
The DD Statements
The next table shows what each DD of the procedure is for.
| DD name | In the procedure | Use |
STEPLIB | DISP=SHR, DSN=HTTPD.LINKLIB | The load library of the server and of the modules of the routes (“The STEPLIB”). |
SYSUDUMP | SYSOUT=* | Not opened by HTTPD. The system writes an abend dump to it. |
HTTPDERR | SYSOUT=* | Standard error of the server. The server opens it at the start. The start code of a server module opens it as well. |
HTTPDOUT | SYSOUT=* | Standard output of the server, opened in the same way. |
HTTPDIN | DUMMY | Standard input of the server. When the DD is missing, HTTPD opens the data set NULLFILE in its place. |
SNAP | SYSOUT=* | Not opened by HTTPD. |
HTTPDBG | SYSOUT=* | The debug output. HTTPD opens it only when the Parmlib member sets DEBUG to a value above 0 (Chapter 1, “The HTTPPRM Keywords”). When it cannot open the DD, it writes HTTPD020E FOPEN FOR DD:HTTPDBG FAILED, ERRNO=n and HTTPD021I DEBUG/TRACE OUTPUT WILL BE TO DD:SYSTERM, and it sends the debug output to the standard error stream, which is the DD HTTPDERR. When a write fails, HTTPD writes HTTPD039W once and stops the debug output until the next start. |
HTTPSTAT | SYSOUT=* | Not opened by HTTPD. |
HTTPPRM | DSN=&D(&M), DISP=SHR,FREE=CLOSE | The Parmlib member (“The Parmlib member”). |
HASPCKPT | A comment line: DISP=SHR,DSN=SYS1.HASPCKPT, UNIT=3350,VOL=SER=MVS000 | The checkpoint data set of JES2, for server modules. Optional (“The JES2 data sets”). |
HASPACE1 | A comment line: DISP=SHR,DSN=SYS1.HASPACE, UNIT=3350,VOL=SER=SPOOL1 | The spool data set of JES2, for server modules. Optional (“The JES2 data sets”). |
Table 29. The DD statements of the procedure
The Parmlib member
The server reads the DD HTTPPRM once, at the start, and to the end. These cases are possible.
- The DD is missing. HTTPD writes
HTTPD020W CANNOT OPEN DD:HTTPPRM -- USING DEFAULTSand starts with its built-in defaults and no routes. - The DD is there and the read fails before the end of the member. HTTPD writes
HTTPD038E READ ERROR ON DD:HTTPPRM -- CONFIGURATION INCOMPLETEand does not start (“Return Codes and Abends”). - Otherwise the server uses the member (Chapter 1, “The HTTPPRM Keywords”).
The standard stream DDs
The procedure must not contain the DD names SYSPRINT, SYSTERM and SYSIN. HTTPD tests for them before anything else. It uses the DD names HTTPDOUT, HTTPDERR and HTTPDIN for its standard streams instead. The routine in front of the server (__premain, in the file httpstrt.c) writes these messages.
| Message | Text and cause |
HTTPD014E | SYSPRINT DD NOT ALLOWED, HTTPD USES HTTPDOUT FOR STDOUT |
HTTPD015E | SYSTERM DD NOT ALLOWED, HTTPD USES HTTPDERR FOR STDERR |
HTTPD016E | SYSIN DD NOT ALLOWED, HTTPD USES HTTPDIN FOR STDIN |
HTTPD017W | HTTPDOUT DD NOT DEFINED, STDOUT IS NOT AVAILABLE. The DD cannot be opened. |
HTTPD018W | HTTPDERR DD NOT DEFINED, STDERR IS NOT AVAILABLE. The DD cannot be opened. |
HTTPD019W | HTTPDIN DD NOT DEFINED, STDIN IS NOT AVAILABLE. The DD cannot be opened, and neither can the data set NULLFILE. |
Table 30. The messages for the standard stream DDs
The routine first tests the three forbidden DDs and writes a message for each one that it finds. When it found one, it stops there. Otherwise it opens the three DDs of the server and writes a message for each that fails. Each of the six conditions ends the routine with EXIT_FAILURE, and the server does not start. The messages with the letter W stop the start as well.
The JES2 data sets
HTTPD does not open HASPCKPT or HASPACE1 itself. A server module runs in the task of the server, because HTTPD starts it with the LINK macro. The module has no allocations of its own and opens a DD name in the allocations of the started task. The jobs API of mvsMF reads the checkpoint and the spool of JES2 through the function jesopen() of the C library.
The two DDs are optional. The sample member has both as comment lines. What jesopen() does depends on the level of the C library that the module is built with:
- With LIBC/370 2.24.0 and later, a DD in the procedure wins. When the procedure has no
HASPCKPT, the function allocatesSYS1.HASPCKPTitself, through the catalog or, when the data set is not cataloged, on the online volume that holds it. When the procedure has noHASPACE1, it allocatesSYS1.HASPACEon the spool volume that the checkpoint names. mvsMF 1.4.0 and later are built with such a level. - With an older level, the function opens only the DD names. The jobs API of mvsMF 1.3.0 and earlier is built this way, and it needs both DDs.
Uncomment both lines of the sample member in these two cases:
- You run mvsMF 1.3.0 or earlier.
- The JES2 of the system builds its data set names with a prefix other than
SYS1(its$DSNPRFXvalue). The allocation looks only for theSYS1names. When it finds no checkpoint, the C library writes the console linesSYS1.HASPCKPT is not cataloged and is on no online volumeandJES2 uses another dataset name prefix than SYS1, or there is no JES2 checkpoint.
Leaving the DDs active in any other system does no harm, because a DD wins. When you uncomment them, UNIT and VOL=SER must match the JES2 procedure of the system. Check them there before the first start. The DDs are DISP=SHR, because JES2 owns the data sets.
When the data sets cannot be reached, the server still starts, and everything except the jobs API works. This holds in both cases above: mvsMF 1.3.0 or earlier without the DDs, and any mvsMF level on a system with another prefix than SYS1 without the DDs. The effect differs by request:
| Request | Answer |
| The job list | Status 500, with the message “Unable to open JES2 checkpoint and spool datasets”. |
| Any request that names a job by name and id, a spool read included | Status 404, “job not found”, although the job exists. The function that looks the job up cannot tell an unreachable JES2 from an unknown job. |
Table 31. A request when the JES2 data sets cannot be opened
Each of these requests writes the console line MVSMF201E UNABLE TO OPEN THE JES2 CHECKPOINT AND SPOOL DATA SETS, and the C library writes the line that names the data set that it could not open. Read the console, not the status code. Submitting a job is not affected, because the submit allocates its own internal reader.
The STEPLIB
HTTPD finds the modules of its routes by the standard search of the LINK macro. It names the module from the MOD= keyword and passes no DCB. The system looks in the STEPLIB of the task first, and then in the link list. The server itself is the program of the EXEC statement. So the STEPLIB holds the server and the modules of the routes, or the link list holds the modules.
The system takes the first library in the concatenation that has the module. Two libraries are in use.
- HTTPD.LINKLIB. The library that SMP installs into. The sample procedure names it. Only the install job writes to it.
- HTTPD.DEV.LINKLIB. The target of
mbt deployin the project file. A deploy deletes the target before it receives into it, because RECEIVE does not merge. For this reason the deploy target is a library of its own and never the production library. Deploying does not activate anything. To run a development build, nameHTTPD.DEV.LINKLIBin a STEPLIB deliberately. The usual way is a second HTTPD on another port. HTTPD refuses a second listener on a port that another HTTPD serves (HTTPD037E, “Return Codes and Abends”), so the production task keeps running. Put the DEV library beforeHTTPD.LINKLIBin the concatenation, so that its modules win.
Stop the task before you replace the load library. The task loads from it.
Authorization
The server needs APF authorization. It tests at entry whether the job step is authorized, and it then makes the task authorized in either case.
- Test. The server issues one TESTAUTH. The test runs before anything else, because after the next step every task is authorized.
- Setup. The server authorizes its task with SVC 244. When the C runtime has recorded that, the server authorizes the STEPLIB in the same way and marks its own entry in the contents directory of the task as an authorized library entry. It then identifies the entry
CTHREADto the system and marks that entry the same way.CTHREADis an entry point inside the load moduleHTTPDand not a member of a library. The server creates its threads through it. The server does this setup also when the step was authorized at entry. - Message. After the version banner the server tells how the step was authorized.
| Message | Meaning |
HTTPD002I AUTHORIZED BY LIBRARY (MODULE KEY 0) | The job step was authorized at entry. The libraries of the STEPLIB are in the list of APF-authorized libraries, or the module is in an authorized library of the link list. The system fetches the module with the protection key 0. |
HTTPD002I AUTHORIZED BY SVC (MODULE KEY 8) | The job step was not authorized at entry. The server authorized the task itself. The system fetched the module with the key 8. |
Table 32. The two ways to be authorized
The key in the message is not measured. The server infers it from the route: a step that is authorized at entry has its module fetched with the key 0, and an unauthorized step has the key 8, and SVC 244 comes too late to change either. The same module behaves differently under the two keys. Chapter 6, “The Server Module Interface” tells what a server module may keep in storage.
The load module HTTPD is linked with the authorization code 1 (ac = 1 in the module definition). SMP copies the module into the library and does not link it again, so the code stays.
The next screen shows a start of the server in a library that is not in the APF list. The server authorized itself by SVC.
S HTTPD
$HASP100 HTTPD ON STCINRDR
$HASP373 HTTPD STARTED
IEF403I HTTPD - STARTED - TIME=05.44.51
HTTPD000I HTTPD 4.5.1 (nnnnnnn) STARTING
HTTPD005I LIBC370 2.26.0 (3AA3B28)
HTTPD002I AUTHORIZED BY SVC (MODULE KEY 8)
HTTPD004I STC IDENTITY SET TO HTTPD/USER VIA RACINIT
RAKF0004 INVALID ATTEMPT TO ACCESS SYSTEM: USER:HTTPPRB
HTTPD036I MODULE MVSMF REGISTERED FOR /zosmf/info
HTTPD036I MODULE MVSMF REGISTERED FOR /zosmf/services/authenticate
HTTPD036I MODULE MVSMF REGISTERED FOR /zosmf/restconsoles/*
HTTPD036I MODULE MVSMF REGISTERED FOR /zosmf/*
HTTPD054I LISTENING ON ANY PORT 8080
HTTPD061I STARTING SOCKET THREAD TCB(9CD7C8) TASK(152FC8) STACKSIZE(32768)
HTTPD061I STARTING WORKER(164D00) TCB(9BBEB8) TASK(166FC8) STACKSIZE(65536)
HTTPD061I STARTING WORKER(164C00) TCB(9BBB88) TASK(177FC8) STACKSIZE(65536)
HTTPD061I STARTING WORKER(164B80) TCB(9BB858) TASK(188FC8) STACKSIZE(65536)
HTTPD001I HTTPD 4.5.1 READY - SERVING /www
When the setup fails, HTTPD writes HTTPD012E name UNABLE TO DYNAMICALLY OBTAIN APF AUTHORIZATION, where name is the name of the program as the system passed it to the server. It does not write HTTPD002I, and the step ends with the return code of the failed call (“Return Codes and Abends”).
At the end the server gives up what it took. It first puts back the security environment that the task had at the start (“The Identity of the Task”), then it releases the authorization of the STEPLIB and of the task with SVC 244.
The Identity of the Task
RAKF has no table of started procedures. It uses the name of the procedure only to find out that the caller is a started task, and it gives every started task the same account, STC/STCGROUP. On a standard RAKF profile set this account holds ALTER authority on every data set of the system. HTTPD does not keep it. At the start the server logs on as the user id of STCUSER and STCGROUP (“The EXEC statement”).
The server reads these two keywords from the PARM string and not from the Parmlib member. The logon must happen before the server reads the member and opens the file system, and these accesses should already run under the new identity.
The logon works in this order:
- The server enters supervisor state with the key 0. When it cannot, it writes
HTTPD003Wand skips the logon. - It remembers the security environment (ACEE) that the task has.
- It calls RACINIT with
ENVIR=CREATEfor the user id and the group, without a password. - When the call works, the new ACEE becomes the resting identity of the address space, and the server writes
HTTPD004I. When it fails, the server writesHTTPD004Wand keeps the identity that the task had.
| Message | Text and cause |
HTTPD004I | STC IDENTITY SET TO user/group VIA RACINIT. The logon worked. |
HTTPD004W | RACINIT ENVIR=CREATE FAILED FOR user/group RC=n. The logon failed, for example because the user id is not defined. The server goes on and keeps the identity that it inherited. |
HTTPD003W | RACINIT SKIPPED, CANNOT ENTER SUPERVISOR STATE. The server could not get the key 0 that RACINIT needs. It goes on with the inherited identity. |
Table 33. The messages for the identity
A failed logon is a warning and does not stop the start. The inherited identity is the more powerful one, so the warning needs action: define the user id.
The new ACEE is not freed while the server runs. The server also keeps the old ACEE and does not release it. When the logon fails, the task would otherwise be left without any identity. At the stop the server puts the old ACEE back before it releases the authorization (“Authorization”). SVC 244 is gated by the profile SVC244 in the class FACILITY, and the task took the authorization out under the old account. The server therefore gives it back under the same account, and the user id of STCUSER needs no access to that profile.
The user id of STCUSER needs READ authority on the Parmlib member and on the document root. A server module that sets no ACEE of its own uses the identity of the task for its accesses.
What the Server Asks of the Security Product
The profiles belong to the site. HTTPD names none of them. The route decides which resource a request is checked against, with the keyword RES= (Chapter 2, “Routes and Authentication Policy”). The server makes these calls.
| Call | Use |
| Logon of the task, RACINIT without a password | The user id of STCUSER must be defined. Without it the server writes HTTPD004W (“The Identity of the Task”). |
Test logon at the start, RACINIT with the user id HTTPPRB and a wrong password | From HTTPD 4.5.1. The server makes this logon once, after the logon of the task and in the same supervisor state. A product that checks refuses it, and RAKF writes RAKF0004. If the product returns an ACEE, it accepts any user id. The server then writes HTTPD042W SECURITY SYSTEM ACCEPTS ANY USERID, ALL LOGINS and refuses every logon of a client (below). There is no test when HTTPD003W skipped the logon of the task, and none later. The user id HTTPPRB is reserved. |
| Logon of a client, RACINIT with user id and password | A route with AUTH=BASIC, AUTH=FORM or AUTH=TOKEN checks the user id and the password of the client. A form login that works gives HTTPD007I, and the release of a credential gives HTTPD008I. From HTTPD 4.5 a logon that fails for a reason other than the password gives HTTPD009W LOGIN SESSION NOT CREATED, RACINIT FAILED RC=n. A wrong password is the client’s doing and is not written to the console. From HTTPD 4.5.1 the server refuses the logon, without a message, when the test logon at the start showed that the product accepts any user id, when the user id is STC, and when the ACEE that comes back names another user than the client sent. Chapter 2, “Routes and Authentication Policy” has the policies. |
Check of a resource for a route with RES=class:resource | The server asks for the access READ. The return codes 0 and 4 allow the request. Return code 4 means that no profile covers the resource. With RES_NOPROFILE=DENY the return code 4 refuses the request (“Authentication Values”). Chapter 2, “Routes and Authentication Policy” describes what happens on a refusal. |
| Probe at the start | For each route with RES= and an AUTH= other than NONE, the server asks once whether a profile covers the resource. It asks as its own identity. Only the return code 4 gives HTTPD425W NO PROFILE FOR class:resource -- path NOT GATED. The route still works, and every request that reaches the check passes. With RES_NOPROFILE=DENY the message is HTTPD426W NO PROFILE FOR class:resource -- path REFUSES ALL REQUESTS, and every request that reaches the check gets status 403. A typing error in the resource name looks like this. A class that RAKF does not define looks like this with RAKF 1.2.x and does not with RAKF 2.0.0, see below. |
| Authorization by SVC 244 | The security product allows or refuses the SVC for the account of the task. The server does not check the profile itself. |
Table 34. The calls to the security product
A refusal is not a missing profile. A resource that is defined and has nobody permitted gives the return code 8, and the probe stays silent. The return code 4 for an unprotected resource is a property of RAKF. Under RACF with PROTECTALL, an unprotected resource gives 8 for an ordinary user and 0 for a SPECIAL user, and a system with no security product gives 0. On those systems the probe stays silent without a profile as well, so a silent probe does not prove that a profile exists. RES_NOPROFILE=DENY acts on the return code 4 only. It does not change what a system answers with 0 or with 8.
The level of RAKF decides what a class that it does not define gives. RAKF 2.0.0 (MVS/CE) gives the return code 8 for a class that is not in the class descriptor table of the system. It writes RAKF0012 UNDEFINED CLASS class to the console. The route refuses every request, the probe stays silent and RES_NOPROFILE changes nothing. A class with a typing error gives this answer. RAKF 1.2.x (measured on TK5) gives the return code 4 for such a class, with no message: the probe writes HTTPD425W or, with RES_NOPROFILE=DENY, HTTPD426W, and without the keyword the route is open. A resource name with a typing error gives the return code 4 on both levels when no profile covers the misspelled name. A measurement with the RAKF of MVS/CE (RAKF 2.0.0) and with that of TK5 (RAKF 1.2.x) gave the return code 0 on both for a batch user, the operator IBMUSER, for the classes TAPEVOL, DASDVOL and TERMINAL without a profile. The start probe, which runs with the identity of the server, stays silent for these classes, so its answer is not 4. HTTPD allows a request on the return code 0, so RES_NOPROFILE=DENY does not close such a route. The measurement did not use the ACEE of a client.
The HTTPD User’s Guide shows how to define the profiles with RAKF, in “Authentication and Security”.
The Start in Order
The server does these steps in this order.
- The routine in front of the server tests the standard stream DDs (“The standard stream DDs”).
- The server tests the authorization and sets it up (“Authorization”). When the setup fails, it writes the banner and
HTTPD012Eand ends. - The banner:
HTTPD000I HTTPD version (commit) STARTING, thenHTTPD005Iwith the version of the C runtime, thenHTTPD006W BUILT FROM A MODIFIED WORKING TREEonly for a build that contains changes that were not committed, thenHTTPD002I. - The server gets the console interface. Without it, it writes
HTTPD090E UNABLE TO INITIALIZE CONSOLE INTERFACEand ends. - The server reads the PARM string and sets the identity (“The Identity of the Task”).
- The server reads the Parmlib member (“The Parmlib member”). Each route is registered as it is read, with
HTTPD036Ifor a module andHTTPD417Ifor a location. When a route lost its policy, the server writesHTTPD420E ROUTE AUTHORIZATION POLICY INCOMPLETE -- HTTPD WILL NOT STARTand ends before it opens the port. - The server sets up the codepage tables, initializes the file system and opens the debug DD when the member asks for it. A file system that does not start gives
HTTPD044W UNABLE TO INITIALIZE FILE SYSTEM. The server goes on without static file serving. - The server binds the listener (“The listener”).
- The server tests the SMF recording. When a level is set and SMF is not active, it writes
HTTPD430W SMF TYPE n CONFIGURED BUT SMF INACTIVE(Chapter 8, “SMF Records”). - The server probes the
RES=profiles (“What the Server Asks of the Security Product”). The server holds the modules of the routes, unless the Parmlib member switches
RESIDENToff (Chapter 1, “The HTTPPRM Keywords”). For each module it looks up the entry in the library and then loads it once. Three messages are possible, and the route works in each case. The module is fetched for each request.HTTPD440W MODULE name NOT FOUND AT STARTUP, NOT HELD— the module is not in the STEPLIB or the link list.HTTPD441W MODULE name NOT REUSABLE, FETCHED PER REQUEST— the module is linked neither reentrant nor serially reusable.HTTPD442W MODULE name LOAD FAILED, ABEND CODE Sxxx REASON rr, FETCHED PER REQUEST.
- The server creates the socket thread with a stack of 32 KB. When it cannot, it writes
HTTPD033E UNABLE TO CREATE SOCKET THREADand ends. - The server creates the pool of worker threads. A worker has a stack of 64 KB. A
MAXTASKof 0 gives 9, and aMINTASKof 0 gives 3. WhenMINTASKis larger thanMAXTASK, the server raisesMAXTASKto the value ofMINTASK. When it cannot create the pool, it writesHTTPD034W UNABLE TO CREATE WORKER THREADS, DYNAMIC DOCUMENTS DISABLEDand goes on. - Each thread writes
HTTPD061I STARTING ...when it starts. - The server sets up the key for the credentials. When that fails, it writes
HTTPD047E UNABLE TO INITIALIZE SERVER CREDENTIAL KEY, RC=nand goes on. The key is new at every start. - The server waits until the socket thread is in its accept loop. It tests up to 50 times at an interval of 100 ms, which is 5 seconds. A healthy start does not wait. When the thread is not running, the server writes
HTTPD064E SOCKET THREAD IS NOT RUNNING, START ABANDONEDand stops. - The server allows 5 queued console commands (Chapter 3, “Console Commands”) and writes
HTTPD001I HTTPD version READY - SERVING docroot. Without a document root the text isHTTPD001I HTTPD version READY - NO DOCUMENT ROOT. The version in the message is in upper case.
The main task then waits for console commands.
The next screen shows a start with a second member of the Parmlib, which defines more routes. The screen is the real console output of a test system.
S HTTPD,M=HTTPPRM1
$HASP100 HTTPD ON STCINRDR
$HASP373 HTTPD STARTED
IEF403I HTTPD - STARTED - TIME=05.38.23
HTTPD000I HTTPD 4.5.1 (nnnnnnn) STARTING
HTTPD005I LIBC370 2.26.0 (3AA3B28)
HTTPD002I AUTHORIZED BY SVC (MODULE KEY 8)
HTTPD004I STC IDENTITY SET TO HTTPD/USER VIA RACINIT
RAKF0004 INVALID ATTEMPT TO ACCESS SYSTEM: USER:HTTPPRB
HTTPD036I MODULE MVSMF REGISTERED FOR /zosmf/info
HTTPD036I MODULE MVSMF REGISTERED FOR /zosmf/services/authenticate
HTTPD036I MODULE MVSMF REGISTERED FOR /zosmf/restconsoles/*
HTTPD036I MODULE MVSMF REGISTERED FOR /zosmf/*
HTTPD036I MODULE HTTPDSRV REGISTERED FOR /.dsrv
HTTPD036I MODULE HTTPDM REGISTERED FOR /.dm
HTTPD036I MODULE HTTPDMTT REGISTERED FOR /.dmtt
HTTPD417I LOCATION /pub/* REGISTERED
HTTPD417I LOCATION /private/* REGISTERED
HTTPD417I LOCATION /form/* REGISTERED
HTTPD417I LOCATION /token/* REGISTERED
HTTPD417I LOCATION /admin/* REGISTERED
HTTPD417I LOCATION /denied/* REGISTERED
HTTPD054I LISTENING ON ANY PORT 8080
HTTPD061I STARTING SOCKET THREAD TCB(9CD6E8) TASK(1A6FC8) STACKSIZE(32768)
HTTPD061I STARTING WORKER(0FE748) TCB(9BBA58) TASK(1BAFC8) STACKSIZE(65536)
HTTPD061I STARTING WORKER(0FE648) TCB(9BB328) TASK(1CBFC8) STACKSIZE(65536)
HTTPD061I STARTING WORKER(0FE5C8) TCB(9BAEB8) TASK(1DCFC8) STACKSIZE(65536)
HTTPD001I HTTPD 4.5.1 READY - SERVING /www
The listener
The server binds to all interfaces of the host (INADDR_ANY). The steps are:
- The server takes an ENQ of the scope SYSTEM with the major name
HTTPDand the minor nameHTTPD.PORT.nnnnn, wherennnnnis the port with 5 digits. The server asks for the resource and does not wait. When another address space holds the resource, or the ENQ fails for another reason, HTTPD writesHTTPD037E HTTPD IS ALREADY ACTIVE ON PORT n, THIS INSTANCE ENDSand ends. A second server on another port starts. The system releases the ENQ when the task ends, also after an abend. - The server creates the socket. When that fails, it writes
HTTPD028E SOCKET() FAILED, RC=n ERRNO=n. - The server binds the socket. When the bind fails with EADDRINUSE, the server closes every socket that is bound to the port in the socket table. Sockets of an earlier instance that ended without closing them are among these. When it closed any, it waits and tries the bind once more.
- When the bind still fails, the server writes
HTTPD030E BIND() FAILED FOR HTTP PORT, RC=n ERRNO=n. With EADDRINUSE it tries again up toBIND_TRIEStimes. Before each try it writesHTTPD030I EADDRINUSE, WAITING FOR TCPIP TO RELEASE HTTP PORT nand waitsBIND_SLEEPseconds. When no try works, it writesHTTPD030Ea second time and ends. A bind that fails with another error gets the secondHTTPD030Ewithout a retry. - The server calls listen with the queue length of
LISTEN_QUEUE. When that fails, it writesHTTPD031E LISTEN() FAILED, RC=n ERRNO=nand ends. - On success the server writes
HTTPD054I LISTENING ON ANY PORT n.
Chapter 1, “The HTTPPRM Keywords” lists the keywords PORT, BIND_TRIES, BIND_SLEEP and LISTEN_QUEUE with their ranges.
Return Codes and Abends
The step ends with return code 0 after a normal stop with P HTTPD (Chapter 3, “Console Commands”). The server issues no user abend. The next table lists every other way that the step ends by the decision of the server.
| Return code | Cause and message |
| 8 | The server refused the start while it read the Parmlib or opened the port. The causes are a member that could not be read to the end (HTTPD038E), a route whose policy is incomplete (HTTPD420E), a port that another HTTPD serves (HTTPD037E), a failed socket call (HTTPD028E), a failed bind (HTTPD030E) and a failed listen (HTTPD031E). |
| 8 | The socket thread could not be created (HTTPD033E), or it is not running after 5 seconds (HTTPD064E). |
| 8 | The task has no COM area, so the commands MODIFY and STOP cannot work (HTTPD090E). |
| not 0 | The authorization failed. When SVC 244 fails, HTTPD writes HTTPD012E and the step ends with the return code of that call. When a later part of the setup fails, the step ends with its return code, for example 4 when the module entry is not found, and the server writes no message and no HTTPD002I. |
Table 35. The return codes of the job step
In the first two rows, the server has started its stop sequence when it ends. It writes HTTPD098I HTTPD SHUTTING DOWN and HTTPD099I HTTPD SHUTDOWN COMPLETE, and the message that names the cause comes before them. The code 8 is what tells a refused start from a normal stop.
The next messages do not change the return code.
| Message | Effect |
HTTPD003W, HTTPD004W | The server runs with the inherited identity (“The Identity of the Task”). |
HTTPD020W | The server runs on the built-in defaults. |
HTTPD034W | The server runs without worker threads. |
HTTPD039W | The server runs with the debug output off. |
HTTPD044W | The server runs without a file system. |
HTTPD047E | The server runs, and logins do not work. |
HTTPD440W, HTTPD441W, HTTPD442W | The route works. The module is fetched for each request. |
HTTPD912E | TERMINATE FAILED WITH RC=......... The stop sequence itself failed. The code of the step stays as it was. |
Table 36. Messages with no effect on the return code
The routine in front of the server (“The standard stream DDs”) ends with EXIT_FAILURE for the messages HTTPD014E to HTTPD019W.
A worker thread is protected by a recovery routine. These two messages concern an abend while a worker serves a request:
HTTPD062E ABEND xxxxxxxx IN WORKER(aaaaaa) CLIENT(aaaaaaaa) SOCKET(n)names the abend code in hexadecimal. The worker goes on with the next request. The server does not stop.HTTPD063E NO RECOVERY IN WORKER(aaaaaa), CLIENT(aaaaaaaa) SOCKET(n) DROPPEDis written when the recovery routine of the worker could not be set up. The client is dropped without an answer.
The module ABEND0C1 abends on purpose to test this recovery (Chapter 7, “The Display Modules”). It writes HTTPD921W ABEND0C1 ALLOCATED n KB IN n BLOCKS, ABENDING WITHOUT FREEING first. Appendix A, “Messages” lists every message with its meaning.
The Package
HTTPD comes as an SMP4 function. The command mbt package writes the archive. This section is the map of what the archive contains and what the install job does. The HTTPD User’s Guide explains how to install it, in “Installing HTTPD”.
The FMID
The FMID of a release is THTP and three digits: the major version, the minor version and the patch version. HTTPD 4.4.0 is THTP440, and HTTPD 4.5.0 is THTP450. A release spends its FMID once, and the FMID is never used again. No component of the version may exceed 9, because a FMID has 7 characters and no room for a second digit. A patch is a new function level and not a PTF on the old one. The package build makes no PTF.
The build derives the FMID and the predecessor from the version in the project file. Version 4.5.0 gives THTP450 and deletes THTP440. A patch release needs an explicit FMID.
Each release deletes its predecessor. The SYSMOD carries a ++VER statement with the operand DELETE, for example ++VER(Z038) DELETE(THTP430) in the package of 4.4.0. SMP keys the ownership of an element on the name of the module and not on the library. A SYSMOD that does not own the module HTTPD cannot install it, and the install then copies nothing while every condition code reads success. The DELETE passes the ownership on. SMP deletes the load modules of the old FMID from the target library and copies the new ones in.
The deleted FMID has no backup entry in the SMP data set. For this reason the APPLY of an upgrade ends with return code 4, and the install job lets the ACCEPT run for a code of 4 or less. A return code does not show that the work was done. List the members of HTTPD.LINKLIB after an install, and look for the message HMA2380 (copy successful).
The names of the data sets carry no version. There is one installation, and an upgrade installs into the same libraries. The allocation job is run once.
The files in the archive
The archive contains these files. The word version is the version of the release, for example 4.4.0-dev for a development build.
| File | Contents |
README.md | The installation guide of the product. |
httpd-version-load.xmit | The load modules, as an XMIT file. |
httpd-version-samplib.xmit | The sample library, as an XMIT file. |
httpd-version-alloc.jcl | The job that allocates the data sets of SMP. |
httpd-version-inst.jcl | The job that installs the SYSMOD. |
httpd-webroot.img | The document root as a UFS370 image. SMP does not know it. |
Table 37. The files in the archive
The XMIT files are uploaded in binary, as RECFM=FB with LRECL=80, to data set names of the operator’s choice. The install job names them in the operands INDSN of its two RECEIVE steps, and these are the only lines that the operator changes in it.
The data sets
| Name | DSORG | RECFM | Space | Use |
HTTPD.LINKLIB | PO | U | CYL (5,2,20) | The target library of SMP, with BLKSIZE 15040. The STEPLIB of the procedure names it. Only the install job writes to it. The allocation job creates it. |
HTTPD.AHTTPLOD | PO | U | CYL (5,2,20) | The distribution library of SMP, with BLKSIZE 15040. The ACCEPT fills it. A RESTORE returns to it. The allocation job creates it. |
HTTPD.HTTPLOAD | PO | by RECEIVE | by RECEIVE | The staging library. The install job receives the load XMIT into it and deletes it at the end. |
HTTPD.SAMPLIB | PO | by RECEIVE | by RECEIVE | The sample library, created by TSO RECEIVE. SMP does not own it. |
HTTPD.WEBROOT.UFS | PS | U | 4096-byte blocks (256) | The disk image of the document root, with BLKSIZE 4096. The job HTTPWEBR allocates it, and the operator uploads the image into it. SMP does not own it. |
Table 38. The data sets of the package
The allocation job sets no LRECL for the two load libraries. The two data sets that TSO RECEIVE creates get their attributes from the XMIT files.
The allocation job has no DELETE step, on purpose. Once the FMID is accepted, the distribution library holds the accepted copy of every element. A job that scratched it again would leave the SMP inventory reporting “accepted” with an empty library behind it. The space is in cylinders, because a space in tracks reaches the limit of 16 extents long before the volume is full. The job uses UNIT=SYSDA. Change the unit and the volume in the job if you want others.
The install job runs these steps in this order.
| Step | Action |
DELOLD | IDCAMS deletes HTTPD.HTTPLOAD and HTTPD.SAMPLIB. SET MAXCC=0 lets a first install pass, where neither exists. TSO RECEIVE does not merge into an existing data set, so the step makes the job run more than once. |
RECV1 | TSO RECEIVE of the load XMIT into HTTPD.HTTPLOAD. |
RECV2 | TSO RECEIVE of the sample XMIT into HTTPD.SAMPLIB. |
RECV | SMP RECEIVE of the SYSMOD. The SYSMOD is part of the job as in-stream data and contains the JCLIN. |
APPLYCHK | SMP APPLY with the operand CHECK. It changes nothing. The next step runs only if this step ends with code 0. |
APPLY | SMP APPLY. It copies the modules into HTTPD.LINKLIB. |
ACCEPT | SMP ACCEPT. It runs when the APPLY ended with a code of 4 or less. It makes this level the base of a later RESTORE. |
CLEANUP | IDCAMS deletes HTTPD.HTTPLOAD. It runs only when the ACCEPT ended with code 0. Comment the step out to keep the library. |
Table 39. The steps of the install job
The JCLIN of the SYSMOD copies the members with IEBCOPY from HTTPD.AHTTPLOD to HTTPD.LINKLIB and lists five modules. SMP does not link them again, so every attribute stays as the linkage editor of the build set it, including the authorization code of the server.
The sample library is not part of SMP. The configuration pattern has comment lines that reach column 80, and an MCS card ends at column 72. The product owns the patterns in the library, and the site owns the copies that it makes.
The members
The load library HTTPD.LINKLIB has five members. All five are linked reentrant and serially reusable.
| Member | Contents |
HTTPD | The server. It is the only member that a started task names. It is linked with the authorization code 1 and contains the entry point CTHREAD. |
HTTPDSRV | The display of the control blocks of the server (Chapter 7, “The Display Modules”). |
HTTPDM | The display of storage (Chapter 7, “The Display Modules”). |
HTTPDMTT | The display of the master trace table (Chapter 7, “The Display Modules”). |
ABEND0C1 | The abend test (Chapter 7, “The Display Modules”). |
Table 40. The members of HTTPD.LINKLIB
All five modules ship, because the package build packages every module and has no way to exclude one. A module is inert unless a route of the Parmlib member names it. The line for ABEND0C1 in the sample member is a comment, and so are the lines for the three display modules.
The sample library HTTPD.SAMPLIB has three members.
| Member | Contents |
HTTPD | The procedure of this chapter. The operator copies it to the procedure library. |
HTTPPRM0 | The pattern for the Parmlib member (Chapter 1, “The HTTPPRM Keywords”). |
HTTPWEBR | The job that allocates HTTPD.WEBROOT.UFS (“The document root disk”). |
Table 41. The members of HTTPD.SAMPLIB
The document root disk
The file httpd-webroot.img is a formatted UFS370 file system with the pages that HTTPD serves from its document root. The operator uploads it with IND$FILE into the data set that the job HTTPWEBR allocated, and mounts it with UFSD.
The job allocates the data set with the attributes that the image needs.
- The data set exists before the upload, because IND$FILE takes the DCB from the label of an existing data set and invents one only for a new data set. The job fixes
BLKSIZE=4096, the block size that the image was formatted with. UFSD compares the two at MOUNT and refuses a mismatch withUFSD062E SUPERBLOCK VALIDATION FAILED FOR dsn. - The space is in the primary extent only. The file system is addressed by block number inside the primary extent, so a block in a secondary extent would never be reached.
- The space is 256 blocks of 4096 bytes, which is the 1 MB of the shipped image. MVS rounds the request up to a track. The superblock and not the data set says how large the file system is.
- The job card has no NOTIFY operand. The value
NOTIFY=&SYSUIDis replaced only by TSO SUBMIT and mvsMF, and any other way to submit gets IEF627I and a JCL error.
An image that is larger than the shipped one needs a larger space. Count it in blocks of 4096 bytes. The HTTPD User’s Guide shows the whole procedure, in “Installing HTTPD”.