Operating System - OpenVMS
cancel
Showing results for 
Search instead for 
Did you mean: 

DCL - Does a process with this PID exist?

 
SOLVED
Go to solution
Jim Geier_1
Regular Advisor

DCL - Does a process with this PID exist?

I encounter many situations in DCL in which the logic knows a PID, and needs to know if the process exists. If it were a device, I'd use f$getdvi with the "exists" argument. It seems to me that a glaring omission from f$getjpi is lack of an "exists" argument. I typically use something like the following, but it is hardly elegant:

$ on warning then continue
$ info = f$getjpi(pid,"master_pid")
$ if f$message($status,"ident") .eqs. "%NONEXPR"
$ then
$ write sys$output "Process does NOT exist"
$ else
$ write sys$output "Process exists"
$ endif

Not particularly pretty... What is your favorite and most elegant means for determining whether a process exists?
17 REPLIES 17
labadie_1
Honored Contributor

Re: DCL - Does a process with this PID exist?

May be you could loop with f$context to see if you pid is here ?

Changing a little bit the example below should be enough
http://h71000.www7.hp.com/doc/73final/6489/6489pro_046.html
Richard Brodie_1
Honored Contributor

Re: DCL - Does a process with this PID exist?

$ if f$getjpi(pid,"pid") .eqs. pid then ...

Duncan Morris
Honored Contributor

Re: DCL - Does a process with this PID exist?

Richard,

that relies on the incoming PID being 8 chars long, which may not be the case in standalone systems if the value is passed in from another source.

You also get a DCL wobbly when running with a non-existant PID

$ set ver
$ if f$getjpi(p1,"pid") .eqs. p1
%SYSTEM-W-NONEXPR, nonexistent process
\1\
$ then
%DCL-E-INVIFNEST, invalid IF-THEN-ELSE nesting structure or data inconsistency
DEVT02>

Duncan
Duncan Morris
Honored Contributor

Re: DCL - Does a process with this PID exist?

Jim,

a snippet from one of our procedures:

$! Get process ID of job
$ jobPID = f$trnlnm("xyz_pid")
$ usenam = f$getjpi(jobPID,"USERNAME")
$ if $severity .eqs. 1 .and. jobPID .nes. ""
$ then
$ ! Process exists
$ write sys$output "PID exists"
$ else
$ ! Process does not exist
$ write sys$output "PID missing"
$ endif
$

Duncan
Robert Gezelter
Honored Contributor

Re: DCL - Does a process with this PID exist?

Jim,

It is certainly awkward. One can scan the process list, or one can use SPAWN/OUTPUT=NL: to do a SHOW PROCESS/ID=xxx command (and then check $STATUS).

- Bob Gezelter, http://www.rlgsc.com
Hoff
Honored Contributor

Re: DCL - Does a process with this PID exist?

Elegance and DCL are not often used in the same sentence.

Why change? (Seriously.) I'm usually in favor of increased elegance, but I'm usually rather more in favor of stable and functional and tested. What you have might be ugly, but it has the very significant advantage of "it works."

Another approach here is to better synchronize the operations and to manage the processes more directly, as cases where you can encounter stale PIDs can have other implications. What happens when you have a valid PID and your f$getjpi returns the MASTER_PID, but the process then immediately exits.

And just for fun (and entirely orthagonal to any elegance), here's one "one-line" DCL approach:

$ pipe define foo/job/nolog "0" | ( x = f$getjpi("''pid'","MASTER_PID") 2> nla0: > nla0: && define foo/job/nolog &x )

John Gillings
Honored Contributor
Solution

Re: DCL - Does a process with this PID exist?

Jim,

Well, it depends a bit on how bullet proof you want this test to be, and how much time you want to spend testing it.

Dealing with a non-numeric or non-existant symbol "pid" is fairly easy:

$ tpid=F$FAO("!8XL",F$INTEGER("%X''pid'"))

tpid is now an 8 digit hex string, either the same as the original or 0. If it's zero F$GETJPI will return information about the current process, so:

$ IF F$$GETJPI(tpid,"PID").EQS.tpid THEN process exists and is not myself

However, that won't deal with the case where "pid" is a valid hex string with no corresponding process. Using brute force, pure DCL, the quickest way might be a SEARCH of SHOW SYSTEM/CLUSTER:

$ PIPE SHOW SYSTEM/CLUSTER | SEARCH SYS$PIPE "''tpid' " >nl: 2>nl:
$ IF $SEVERITY.EQS."1" THEN process exists

Note, this may give a false positive because it will match a PID string anywhere in the output (like a process name). The trailing space will help, but is not foolproof.

An F$CONTEXT loop across the cluster is safer, and may be quicker than the PIPE, but is more code.

If you're prepared to go with a program, here's a simple MACRO32 program that accepts a PID string (as a foreign command argument) and returns status %X10000001 if the process exists, %X100008E8 (%SYSTEM-W-NONEXPR, nonexistent process) if it doesn't exist and %X10000000 if the PID string is invalid.

.title checkpid
.psect data,rd,wrt,noexe
pid: .LONG 0
pidnew: .LONG 0
pidret: .LONG 0
pidstr: .ASCID /00000000/
$JPIDEF
item: .LONG JPI$_PID
.psect code,rd,nowrt,exe
.entry start,^M<>
; get argument
PUSHAB pidstr
CALLS #1,G^LIB$GET_FOREIGN

; convert to longword integer
PUSHAL pid
PUSHAB pidstr
CALLS #2,G^OTS$CVT_TZ_L

; get PID from $GETJPI
MOVL pid,pidnew
PUSHAL pidret
PUSHL #0
PUSHAL pidnew
PUSHAL item
CALLS #4,G^LIB$GETJPI

CMPL pid,pidnew ; check same
BEQL fin
MOVL #0,R0
fin: ADDL2 #^X10000000,R0
RET
.end start
A crucible of informative mistakes
Jess Goodman
Esteemed Contributor

Re: DCL - Does a process with this PID exist?

Using PIPE to turn off error messages in a one-liner is a good idea, but since F$GETJPI already returns status value %SYSTEM-W-NONEXPR, as your example shows, why not just:

$ PIPE PID = F$GETJPI(PID,"PID") 2>NL: >NL:
$ IF F$MESSAGE($STATUS,"IDENT").EQS."NONEXPR"
$ THEN ...

The symbol PID will not be updated on any F$GETJPI error, and if F$GETJPI succeeds it will get the normalized (8 upper-case hex digits) string version of what PID was before.

If you just want to check the symbol PID after the PIPE command you could use:
$ PIPE PID = F$GETJPI(PID,"PID") 2>NL: >NL: || PID=-1

which will set PID to -1 when the process does not exist (but -1 also on any other F$GETJPI error such as %SYSTEM-F-NOPRIV).

As to using F$CONTEXT, if you know that your process is on the current node and is not a subprocess then this would work:

$ DUMMY=F$CONTEXT("PROCESS",CTX,"MASTER_PID",PID,"EQL")
$ IF F$PID(CTX).EQS."" THEN !No such process
$ DELETE/SYMBOL CTX

If the process can be on other nodes then add
$ DUMMY=F$CONTEXT("PROCESS",CTX,"NODE_CSID",0,"NEQ")

Hoff's point about the race-condition that exists if you are first checking if a process exists, and then doing something to/for it if it *does*, is quite valid. So I'm guessing that you want to do something when the process does *not* exist.
I have one, but it's personal.
John Gillings
Honored Contributor

Re: DCL - Does a process with this PID exist?

Ah, I like Jess's idea...

I'd forgotten that a single stage PIPE command is executed in the context of the current process. That makes it cheap, and it can return symbol values.

So, combining my trick for "cleaning" the PID string, and Jess's for testing it, we get:

$ PIPE newpid=F$GETJPI(F$FAO("!8XL",F$INTEGER("%X''pid'")),"PID") >NL: 2>NL:
$ ProcessExists=$STATUS.AND.-
F$INTEGER("%X''newpid'").EQ.F$INTEGER("%X''pid'")

This will work correctly for any value of PID, including null and undefined. Adding the F$INTEGERs to compare newpid and pid allows leading zeros in the PID string to be omitted.
A crucible of informative mistakes