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

timeout for sys$waitfr

 
SOLVED
Go to solution
Alex Chupahin
Super Advisor

timeout for sys$waitfr

Hello dear guru,
I just looking to something with event flags technique.
There are a couple calls for wait the flags
SYS$WAITFR SYS$WFLAND SYS$WFLOR
all will wait infinity time until the flag(s) have been set.
But I wish to wait only a fixed time period.
This is code example:

/*---------------------------*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include

#include "errchk.h"


/******************************************************************************/
static void ast_routine (unsigned int efn) {

static unsigned long int r0_status;

r0_status = sys$setef (efn);
errchk_sig (r0_status);
}


/******************************************************************************/
int main (void) {

static IOSB iosb;

static unsigned long int r0_status;
static unsigned int pid;
static unsigned int group;
static unsigned int member;

static char username[12];
static unsigned short int username_len;
static unsigned int efn;

static ILE3 jpiitms[] = { 4, JPI$_PID, &pid, NULL,
4, JPI$_GRP, &group, NULL,
4, JPI$_MEM, &member, NULL,
12, JPI$_USERNAME, username, &username_len,
0, 0, NULL, NULL };


r0_status = lib$get_ef (&efn);

r0_status = sys$getjpi (EFN$C_ENF,
0,
0,
jpiitms,
&iosb,
ast_routine,
efn);
errchk_sig (r0_status);

/*
** Wait for the event flag to be set by the AST.
*/
r0_status = sys$waitfr (efn);
errchk_sig (r0_status);

r0_status = lib$free_ef (&efn);
errchk_sig (r0_status);
}
17 REPLIES 17
Alex Chupahin
Super Advisor

Re: timeout for sys$waitfr

Can anybody help me how to transform it with waiting for flag event only for a fixed time period?
RBrown_1
Trusted Contributor
Solution

Re: timeout for sys$waitfr

The usual method is to use two event flags. Have one set by your call to SYS$GETJPI and the other by a call to SYS$SETIMR to set your timeout. Then just use a SYS$WFLOR and then check your iosb to see which one completed.

WRT your sample code, it appears that your ast serves no purpose, since your ast_routine simply sets the event flag, the call to SYS$GETJPI is coded to set the event flag anyway. Personally, I would get rid of the ast routine.

hth
GuentherF
Trusted Contributor

Re: timeout for sys$waitfr

Alex,

add a sys$setimr call with an AST in which you set efn. Also add a sys$cantim in your ast_routine to remove the outstanding timer event in case the sys$getjpi finishes first to prevent firing the timer AST later on.

You may pass a longword[2] array as AST parameter to your ast_routine which contains the event flag number and the reqid from the sys$setimr call so you can cancel the timer event.

Specify EFN$C_ENF (=no event flag) in the sys$setimr call because you only use the AST method for triggering.

/Guenther
Hoff
Honored Contributor

Re: timeout for sys$waitfr

What's your goal here? (I do understand what that C code is doing, but not why; what the goals and requirements here might be here.)

There are several ways this question could go. Interestingly, all of which involve expunging the event flags for all but the simplest use.

Are you looking specifically for the PID, username and group? If so, expunge the event flags...

Are you looking to learn AST programming here? (If so, then expunge the event flags, and replace that ASTPRM with a malloc'd context block structure, and pass the R0 value and the IOSB that way.)

Might sys$getjpiw() work better here? If so, expunge the event flags...

Might sys$synch work better here? Expunge the event flags...

Are you looking to continue trying to pound the hack that is an event flag into something more functional? Or are you open to alternatives? In all bluntness, event flags are a massive hack and something best avoided for all but the simplest cases, and best expunged.

Oh, and remember to expunge the event flags. Did I mention I'm not fond of event flags? Oh, and event flags WILL cause you headaches in all but the simplest cases.

If it's not clear, event flags are not something that I'd suggest using in all but the simplest of cases.

There are some coding errors here, not the least of which is the mishandling of the static values; that r0_status value gets reused, which well could mean the tests are going to behave oddly. (There's an AST here that can hit between the end and the return from the $getjpi and the immediately-subsequent errchk_sig() call here, and that AST overwrites r0_status.)

Don't forget to get rid of those event flags, too.
H.Becker
Honored Contributor

Re: timeout for sys$waitfr

>>>There are some coding errors here, not the least of which is the mishandling of the static values; that r0_status value gets reused...

I don't see such a coding error. r0_status has local scope and global duration, that doesn't make r0_status in main accessible to ast_routine. If static is necessary, is a good style and results in good performance is a different question.
John McL
Trusted Contributor

Re: timeout for sys$waitfr

The addresses of the PID and the process name are 0 so you're doing a $GETJPI on the calling process. I doubt very much that you'd have a potential problem with the $GETJPI call timing out.
Robert Gezelter
Honored Contributor

Re: timeout for sys$waitfr

Alex,

For the most part, I agree with Hoff. Event flags are a concept that is useful in fairly simple code, which functionally almost always means "get rid of them".

The example of using an AST to set an event flag is an echo from a poorly chosen example long ago in the RSX-11 Executive manual. When I started on RSX, that example never made sense to me. It seemed pointless. Reviewing the source listings, I found out how ASTs were really used in the code base, and the concept made far more sense.

If you are doing GETJPI against the current process, the timeout is not a real concern. If you are inquiring about another process, the way to do it is by declaring both a GETJPI and a TIMER request, and then doing what is appropriate if the TIMER fires first. One must remember that ASTs are FIFO and non-premptable WITHIN A PROCESS. One must also consider the possibility that the TIMER request will fire while the AST for the GETJPI is running. A common error in these situations is one or more dangling pointers.

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

Re: timeout for sys$waitfr

Alex,

I'm with Hoff. Event flags are very limited and have all kinds of nasty potential timing issues. They made a bit more sense long ago in the days of uniprocessors (but not much!). These days I usually stick with EFN$C_ENF and try to forget that event flags exist.

For asynchronous requests that don't have timeout options, you can usually implement your own using "crossed ASTs". The basic principle is

1) set a timer AST, which cancels the event request and issues a $WAKE,
2) make the request , specifying an AST which cancels the timer and issues a $WAKE
3) $HIBER (waiting for event or timer) work out what happened by looking at the IOSB.

This works for most things, BUT realise that $GETJPI has no cancel mechanism. So, if you timeout, you leave resources pending. There's a potential to deplete resources, like ASTLM, especially with a short timeout. You also need to be VERY careful with reusing variables in subsequent asynch calls. For example, you can't reuse the IOSB for calling another $GETJPI before the previous one has completed.

As John McL says, a timeout $GETJPI against yourself is extremely unlikely, but if you're scanning multiple processes in a large cluster, you might get into trouble.

If you insist on using event flags, you can do what you want by scheduling a timer to set the EFN you're waiting for, or use a second flag and $WFLOR the pair of them. You may also want to consider allocating yourself an EFN longer term. LIB$GET_EF and LIB$FREE_EF are fairly cheap, but if you're concerned enough about time to worry about $GETJPI...
A crucible of informative mistakes
GuentherF
Trusted Contributor

Re: timeout for sys$waitfr

Oh guys, you have the world's answer. I think Alex was using the getjpi example to ask for how in general to timeout a sys$waitfr. (my guess)

If it was just about sys$getjpi...hello... there's a sys$getjpi"W", which btw. could go across the cluster and could be delayed up-to RECNXINTERVAL.

Cheers,
Guenther