Operating System - OpenVMS
1828371 Members
3032 Online
109976 Solutions
New Discussion

Re: 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
Alex Chupahin
Super Advisor

Re: timeout for sys$waitfr

Yes, I see I make some fusion with this sys$getjpi... sorry. This is only an example that set up the event flag....
No reason to treat it as final conclusion.
I'm in search to find a way with signaling technique. The software I porting use poll for it (such a strange idea I think). I wish to remove poll for OpenVMS and use event flag. But I need to wait events for fixed time period.
Ian Miller.
Honored Contributor

Re: timeout for sys$waitfr

If the intent is to pause for a specified delay then use lib$wait
____________________
Purely Personal Opinion
Robert Gezelter
Honored Contributor

Re: timeout for sys$waitfr

Alex,

The only words that come to mind when "polling" is mentioned as a technique are not usable in a gentlemen's [gentleperson's ?] forum. {To be precise, they are associated with various ailments of the mammalian digestive tract; certainly not pretty.)

Inter-process communications translates the problem into a different realm. There are many side issues, beyond the normal case. Often, I have used DECnet logical links to connect processes. The advantage of this is two fold: the ability to use ASTs as a event notification vehicle, and almost more importantly, OpenVMS' automatic disconnection of a logical link when a process exits for any reason. The disadvantage is that one side of this connection must hold SYSNAM to accept multiple incoming connections from different clients, as is often the case.

Mailboxes can be used to accept streams of event notifications. The problem is that there is generally no notification if the partner process disappears. Fewer privileges are needed in this case.

Event flags, as in cluster common event flags, can also be used. These are event flag groups that are shared among a group of different processes within a common group. I refer you to the OpenVMS Programming Concepts manual for a more detailed description.

I would be very careful about using a single event flag for both TIMER and another operation, as has been mentioned. There are race conditions that can occur, both in the handling of the event flag and in the processing of the other system call. Some of these are subtle.

For example, the following sequence:

Declare Timer
A: Call GetJPI
B: Check if Timer expired

The Timer can expire before the GETJPI has even been queued. If there is a higher priority process on the system. It may not be common, but it can happen. Similarly, even though the Timer fires first, between the timer being fired and the AST being processed, it is possible for the other event to be complete. Extreme caution is recommended to avoid creating a rare and difficult to reproduce failure mode.

- Bob Gezelter, http://www.rlgsc.com

abrsvc
Respected Contributor

Re: timeout for sys$waitfr

Perhaps the bottom line here is that there are many potential implementaion options which each have their strengths and weaknesses. Without a clear understanding of the particulars of hte problem being solved, we can only provide generic methods. This can be either a simple implementation or complex. I tend to prefer the simple solutions as they are less likely to bite me later...

I might suggest that you consult with someone with more VMS experience about the details of the problem. In the interest of full disclosure, many of us here provide such consultation. Your problems may require more detail than can easily be discussed in this forum.

Dan
Hoff
Honored Contributor

Re: timeout for sys$waitfr

The Programming Concepts manual has details on various of the options.

Consider threads.

Or sys$qio or other service with a completion AST; that's event-driven, and may or may not be feasible.

Or a repeating series of ASTs using sys$setimr.

Or issue a sys$schdwk, and a loop. Do something. $hiber. Loop to something. Repeat.

It's possible that the code here may work more or less directly, depending on what's going on within its logic.

What's going on depends on the details of the code, and how far the port can or should diverge from the code.

There are limits around the select() and poll() calls in VMS, though those may be an option.

Event flags and polling are comparatively evil solutions, though the former tends to be more subtle about it.

As fun as it is to rant about the messes that event flags cause, what is the open source package involved, and cam we get a source code pointer to the problematic code? What is the target OpenVMS version and architecture(s) for the port? The C library is a consideration here; the older you aim for with this port, the fewer C calls available.
Craig A Berry
Honored Contributor

Re: timeout for sys$waitfr

If the thing you're waiting on is a file or device, and if the thing you're waiting to have happen is some sort of I/O on that file or device, consider read and/or write attention ASTs. I think details would be in the I/O User's Guide.
Alex Chupahin
Super Advisor

Re: timeout for sys$waitfr

Thanks for help very much, its makes all for me.

Interesting, widely saying, what about good select emulation idea via system service routines?

So, there is a socket array fd_read for read,
there is a
select(1,*fd_read, NULL, NULL, timeval)
for this socket.

What is a good idea to get same functionality with event flags?
Hoff
Honored Contributor

Re: timeout for sys$waitfr

You'll be using system services and specifically $qio or $qiow calls here, with completion event flags or with completion AST calls, depending on your goals.

The RTLs provide wrappers around these services.

The TCP/IP $qio interface is documented in the TCP/IP Services documentation shelf, at hp.com/go/vms/doc

There are examples in the TCPIP$EXAMPLES: directory.