The Mysterious QP0ZSPWP Jobs
QP0ZSPWP jobs are created by spawn() and fork() functions. But what do they do?
This week I’ll take a look at the QP0ZSPWP jobs. You’ve probably seen evidence of them and may have wondered what they do. These jobs are created by spawn() and fork() functions.
Spawn Process is a Unix-type API that creates a new job, called the child process. The child process inherits many attributes of the calling job, called the parent process. There are four variations of the spawn() API that can be used. Spawn() uses batch immediate jobs or prestart jobs for the child process.
Fork400 (and its variations) are used by applications that run in PASE. Fork also initiates child processes, and like spawn, are either batch immediate jobs or prestart jobs.
Spawn() has several flag fields that can be used to influence the attributes inherited by the child process. Of interest for this blog is the ability to request spawn()to use prestart jobs. If you set the flag SPAWN_SETPJ_NP on, spawn() will attempt to use prestart jobs. The child job will have the QP0ZSPWP job name (SPaWn Process) if it’s single threaded, or QP0ZSPWT (SPaWn Threaded) if it is multithread capable. If you don’t use prestart jobs, the default is to name the child job based on the path parameter, although this can be overridden.
IBM i does not ship with prestart job entries for spawn(). By default, spawned jobs run as batch immediate jobs in the same subsystem as the parent job. Batch immediate jobs have many of the same attributes as the parent job and do not go through a job queue. With batch immediate jobs, you incur the overhead of job initiation inline when you spawn the child job.
If you want to use prestart jobs, prestart job entries must be added the appropriate subsystem(s). Using prestart jobs does not eliminate the overhead of starting and ending a job for each spawn invocation. Rather, they move the overhead of job initiation out of the mainline path when spawn is run. Spawn() ignores the MAXUSE parameter of the prestart job entry and the job is only used one time.
Qshell is an example of an application that uses the spawn() API. When you run a command in Qshell, the execution of that command is generally run in a child process. If you’re not using prestart jobs, a batch immediate job is used. If you use prestart jobs, the command will run in a waiting prestart job, which ends when the command is complete.
Qshell is set up to take advantage of prestart jobs by default. If you catch a spawned job in process, you will find they use the job name of QP0ZSPWP, even when run as batch immediate jobs. These spawned jobs are generally invisible because they’re short-lived, generally do not produce job logs, and the CPF1124/CPF1164 messages aren’t logged to the history log.
There are just a few steps to configure Qshell to use prestart jobs.
First, you must add the prestart job entry to the appropriate subsystem—this is likely QINTER. I recommend using the QDFTSVR job description. The values you select for the configuration parameters depend upon your usage.
ADDPJE SBSD(QSYS/QINTER) PGM(QSYS/QP0ZSPWP) INLJOBS(5) THRESHOLD(2) ADLJOBS(3) JOBD(QGPL/QDFTSVR) MAXUSE(1) CLS(QGPL/QINTER)
Next, you need to tell Qshell to use prestart jobs. This is done with the environment variable QSH_USE_PRESTART_JOBS. If you set this environment variable within your Qshell session, use the export command so that child processes will also use prestart jobs:
export -s QSH_USE_PRESTART_JOBS=Y
You can put this environment variable in a location such as /etc/profile so it takes affect for all users.
QP2TERM is an example of an application that uses fork(). Similar to Qshell, the commands entered in QP2TERM generally run in a child process. By default, the child jobs started from QP2TERM are batch immediate jobs with the simple job name of the interactive job that called QP2TERM. There is an ILE environment variable, QIBM_PASE_USE_PRESTART_JOBS, that when set to Y, will direct PASE to use prestart jobs. You can simply set this environment variable in your job prior to calling QP2TERM.
ADDENVVAR ENVVAR(QIBM_PASE_USE_PRESTART_JOBS) VALUE(Y) LEVEL(*JOB)
If you want everyone to use prestart jobs, you can set this environment variable for the system. When PASE fork() uses prestart jobs, the job name is QP0ZSPWT.
You also need to have the prestart job entry added to the appropriate subsystem. For QP2TERM, this is likely QINTER.
ADDPJE SBSD(QSYS/QINTER) PGM(QSYS/QP0ZSPWT) INLJOBS(5) THRESHOLD(2) ADLJOBS(3) JOBD(QGPL/QDFTSVR) MAXUSE(1) CLS(QGPL/QINTER)
When you log into IBM i with SSH, you will discover that your shell runs in a batch immediate job named QP0ZSPWP. It runs in the same subsystem as the SSH Daemon, which defaults to QUSRWRK, but you can set up SSH to run in its own subsystem.
SSH is a PASE application, so you can configure SSH use QP0WSPWT prestart jobs, similar to QP2TERM.
The necessary prestart job entry is slightly different; this example assumes you are running SSH in the QUSRWRK subsystem:
ADDPJE SBSD(QSYS/QUSRWRK) PGM(QSYS/QP0ZSPWT) INLJOBS(5) THRESHOLD(2) ADLJOBS(3) JOBD(QGPL/QDFTSVR) MAXUSE(1) CLS(QGPL/QSYSCLS25)
For SSH, you must set the QIBM_PASE_USE_PRESTART_JOBS environment variable system wide.
ADDENVVAR ENVVAR(QIBM_PASE_USE_PRESTART_JOBS) VALUE(Y) LEVEL(*SYS)
After you have set up the environment variable you need to restart the *SSHD server to pick up the change.
The examples above covered how the Unix-type shells use spawn() or fork() and how you can influence them to use prestart jobs. Any application that uses the spawn() or fork() will have similar considerations. Note that if spawn() or fork() are coded to specify a job name, they will not take advantage of prestart jobs.
About the author
Dawn May is an IBM i consultant. She owns Dawn May Consulting, LLC in the Greater Boston area. Dawn is a former IBM senior technical staff member.
See more by Dawn May