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

Name of the invoking funtion

 
SOLVED
Go to solution
Jairo Alves
Occasional Visitor

Name of the invoking funtion

We wish to print out (log), within a called module, what is the calling module name.

What would you recommend?

Thanks,
Jairo
12 REPLIES 12
RBrown_1
Trusted Contributor

Re: Name of the invoking funtion

In the absence of a better specification, I would try using the traceback handler. Perhaps you could call lib$signal with a status of 3.
Hoff
Honored Contributor

Re: Name of the invoking funtion

What would I recommend?

More words around your problem statement.

This question can go in dozens of directions...

Off the top, what programming language? What version? Operating system platform? Version? Compiled with debug, or not? Are there specific application run-time or traceback requirements? Any specific source code portability requirements?

Some background on the problem, in other words.

If you're catching errors, I might well suggest the process dump mechanism, or dynamically activating the debugger.

For differing requirements, I might then suggest one of the (documented) stack traceback calls.

Here's a write-up on the ACCVIO and infomation on how that works, with links to signal handling and to examples of callable traceback:

http://labs.hoffmanlabs.com/node/800
http://labs.hoffmanlabs.com/node/803
abrsvc
Respected Contributor

Re: Name of the invoking funtion

If you are looking for getting names etc WITHOUT image termination, it is possible but will require programming that is not trivial and likely to be hardware platform dependent and not supported. As was stated before, additional information about what you are attempting and why is necessary for us to provide proper guidance.

Dan
Hein van den Heuvel
Honored Contributor

Re: Name of the invoking funtion


Right, you probably want to call the Trace BacK handler to sort this out.

Documented, with sample code in :

http://h71000.www7.hp.com/doc/83final/4493/4493pro_070.html

support routines used ...

tbk$show_traceback
tbk$i64_symbolize
lib$i64_get_curr_invo_context
lib$get_curr_invo_context
lib$get_prev_invo_context

I have attached a sample function to just return callers name, with integrated test.

hth,
Hein.
Brad McCusker
Respected Contributor

Re: Name of the invoking funtion

It's easy to do from DCL using symbols, assuming you own (i.e. can modify) the calling modules.

Here is a very simple, very NOT robust example. Depending on your environment, you will probably want to add a lot more, particularly in the area of initial invocation and exit and error handling. This is intended purely to provide you an example of the concept, the routine names reflect my opinion of the code:

$ ty junk1.com
$!
$ say := write sys$output
$ if("''p_name'" .eqs. "")
$ then
$ c_proc = "NONE"
$ else
$ c_proc = "''p_name'"
$ endif
$!
$! Name of THIS procedure
$!
$ this_p = f$env("PROCEDURE")
$ p_name = f$parse(this_p,,,"NAME","SYNTAX_ONLY")
$!
$ say "Routine ''p_name', called from ''c_proc'"
$ @junk2.com
$ say "Back to Routine ''p_name', called from ''c_proc'"
$ @junk3.com
$ exit
$
$
$ ty junk2.com
$!
$ say := write sys$output
$ if("''p_name'" .eqs. "")
$ then
$ c_proc = "NONE"
$ else
$ c_proc = "''p_name'"
$ endif
$!
$! Name of THIS procedure
$!
$ this_p = f$env("PROCEDURE")
$ p_name = f$parse(this_p,,,"NAME","SYNTAX_ONLY")
$!
$ say "Routine ''p_name', called from ''c_proc'"
$ @junk3.com
$ say "Back to Routine ''p_name', called from ''c_proc'"
$ exit
$
$
$ ty junk3.com
$!
$ say := write sys$output
$ if("''p_name'" .eqs. "")
$ then
$ c_proc = "NONE"
$ else
$ c_proc = "''p_name'"
$ endif
$!
$! Name of THIS procedure
$!
$ this_p = f$env("PROCEDURE")
$ p_name = f$parse(this_p,,,"NAME","SYNTAX_ONLY")
$!
$ say "Routine ''p_name', called from ''c_proc'"
$ exit
$
$
$ @junk1
Routine JUNK1, called from NONE
Routine JUNK2, called from JUNK1
Routine JUNK3, called from JUNK2
Back to Routine JUNK2, called from JUNK1
Back to Routine JUNK1, called from NONE
Routine JUNK3, called from JUNK1
$

Brad McCusker
Software Concepts International
www.sciinc.com
Brad McCusker
Software Concepts International
Jairo Alves
Occasional Visitor

Re: Name of the invoking funtion

Thanks everyone for the help so far.

I will explain the problem better.

Programming Language: Compaq Fortran 90, OS: OpenVMS 7.3.2, compiled without debug and no special portability requirements.

Apparently, one of our applications is leaving some data files locked, causing the other modules to not be able to access them.

As we do own the reading/writing routines, we would like to log the name of the calling method every time it holds a data file locked. So that whenever an ACCVIO error is thrown, the log file will tell us where the problem lies.

Any help would be appreciated.
Thanks
Hein van den Heuvel
Honored Contributor
Solution

Re: Name of the invoking funtion

>> Apparently, one of our applications is leaving some data files locked, causing the other modules to not be able to access them.

Hopefully the modules running into the record lock report the file/key/value or just report 'waiting for lock on xxx' and actually use RMS to wait for the lock.
In that case it is trivial to use ANAL/SYST... SET PROC ... SHOW PROC/LOCK to identifiy the lock being waited for (8 byte length, RFA contents) and the lock blocking it.

The module doing the lock obviously long since came and went.

>>> As we do own the reading/writing routines, we would like to log the name of the calling method every time it holds a data file locked.

Hmm, that doesn't sound to effective. Log thousands to catch 1?

>> So that whenever an ACCVIO error is thrown, the log file will tell us where the problem lies.

Huh?
1) why would a lock result in an ACCVIO?! Fix that error handler! And if it did ACCVIOP did it not produce a stack dump with MODULE names/line numbers?
2) but the lock might become a problem thousands of operations, hours, after it was obtained.
3) why not report the file/key #, key value and figure out who has the lock, if an when needed?

Attached a program (requires CMEXEC) which can report the lock holder more easily than ANAL/SYSTEM can.

[ I'm thinking of a variant which can be installed with privs and can be requested to report on a lock via mailbox or some such. Contact me if that would help you even more ]

Good luck,
Hein
abrsvc
Respected Contributor

Re: Name of the invoking funtion

You may be overcomplicating things here a bit. As stated earlier, an ACCVIO should create a stack dump including all of the calling/called routines. I'd start there using that info and the .LIS files. Perhaps it is a simple error easily found that way.

Dan
Hoff
Honored Contributor

Re: Name of the invoking funtion

Without intending offense, are you using the OpenVMS Debugger for troubleshooting here, or are you attempting this using logging and embedded print statements for debugging?

(This task is directly within the Debugger's bailiwick. While the OpenVMS Debugger isn't exactly maintaining parity with debugging on other platforms, it's still a useful tool for this task.)

If you're looking for which process has the blocking access, then AMDS or Availability Manager or ANALYZE /SYSTEM or Hein's tools can help; you can trace down the grant lock that way. But most any application that references the file can be a potential culprit for a collision, depending on the timing of the access. Resolving that usually some combination of retries and moving off the lock after a timeout.

If you identify the culprit, then you can send a $forcex or equivalent, and then have a look at the traceback in the target environment for the call chain. Here's the basic sequence:

http://labs.hoffmanlabs.com/node/800

There are tools that send the $forcex to the specified process available from the OpenVMS Freeware, or you can create your own in a dozen lines of C. And recent versions of VMS have a way to do this from the DCL command line; see the STOP /ID /EXIT stuff.

RMS just isn't all that good at this sort of "meta-locking" task, unfortunately; you get to roll your own coordination and your own archival processing atop the RMS locking.
Jairo Alves
Occasional Visitor

Re: Name of the invoking funtion

Thanks Hein, Dan and Hoff.
Sorry I expressed myself wrongly about the ACCVIO. Let me correct it.

Actually, because of the writing routine pre checks, no ACCVIO error does really occur. So, we do not have the stack info to go over.

What happens is that those pre checks throw up a pretty generic 'locked file error' that blocks other modules to access the file.

Hein, your idea is to identify the file holder only when somebody else tries to access it, right? Sounds nice.

Using Just knowing the process name does not really help, because our entire system is compiled as only one executable.
That's why it'd be necessary to identify the calling function name.

Another solution would be to pass the calling function name as an argument to the writing routine, but this would mean thousands of changes to be made throughout the code.

PS.: Hoff, we are using logging and embedded print statements for debugging.
abrsvc
Respected Contributor

Re: Name of the invoking funtion

Since you have the checking for the ACCVIO already in place, why not call LIB$SIGNAL with a success code. That should produce a stack dump (I think) but allow for the program to continue. Worse case scenerio, let the ACCVIO occur in a test case and use that stackdump to locate the problem area. Once located, additional print statements can be added to trace the behavior.

Where are you located? Perhaps a direct connection (if allowed) would be more helpful to track this down.

Dan
Hein van den Heuvel
Honored Contributor

Re: Name of the invoking funtion

Oh boy, there is a lot of opportunity here to improve the language used / communication, and English is NOT the problem. :-)

>> Actually, because of the writing routine pre checks.

What are 'pre-checks', what is a 'write'.
I assume the write is the Fortran language write IO statement.
Are we typically taking about an new record ( RMS $PUT ) or update/re-write ( RMS $UPDATE).
Is the pre-check a Fortran Read to see if the record can be locked.
Hopefully that is done with generating a lock to make sure no other process sneaks in between the check and the actual act ?!

>> no ACCVIO error does really occur.

ACCVIO is NOT normal in OpenVMS applications.
It means that the application, and specifically the error handling, is broken. So you don't program a check to avoid it, you fix it!

>> What happens is that those pre checks throw up a pretty generic 'locked file error' that blocks other modules to access the file.

So _that_ should be you first order of business and may well make everything else go away. Improve that 'pre-check' to identify the file, key, possibly program image name, possibly calling module name(s).

>> Hein, your idea is to identify the file holder only when somebody else tries to access it, right? Sounds nice.

Correct. Like magic :-).

>> Using Just knowing the process name does not really help, because our entire system is compiled as only one executable.

There is that communication problem.
Be careful keep to modules, images, processes and threads well identified.

When you write process-name, I suspect you meant program name = image name

When I see process-name I think PROCESS-ID
= PID = unique process identifier in OpenVMS
= something to kill ( FORCE_EXIT ) to relase a lock.

It could be that the whole application is written as a single process juggling lots of (AST) threads to work for all users, but frankly I highly doubt that. Surprise me!

>> That's why it'd be necessary to identify the calling function name.

For the programs creating the locks (in the past) or for the programs running into a lock?

>> Another solution would be to pass the calling function name as an argument to the writing routine, but this would mean thousands of changes to be made throughout the code.

That's why we learned to write TPU MACROS, DCL or PERL scripts. :-).

>> PS.: Hoff, we are using logging and embedded print statements for debugging

Right. Hoff suggests that there are more often effective methods: debuggers!
But those would only work in the here and now. That is the program/process/thread running into the lock. It is 'tricky' to go back in time and start debugging a lock which should have been released.

btw... there is a trick to activate the debugger 'just in time'. Instead of printing 'help file is locked' call LIB$SIGNAL with SS$_DEBUG as argument. Of course you may want to have DBG$INPUT and DBG$OUTPUT redirected to a (virtual) terminal instead of the screen for some innocent end user.

Speaking of which.. what kind of application is this? interactive - Green Screen' (SMG? FMS? DecFORMS?..), Web-services, Decnet tasks? ACMS...

Good luck!
Hein