Equivalent to INSTANTIATING-PROCEDURE for OO ABL.... when in

Posted by slacroixak on 12-Oct-2016 07:14

At last I ask around about this topic I've been wondering for ages

I'd like to identify the ABL objects or procedures that have caused persistent procedures or objects leaks.

A leakage is easy to spot with the SESSION:FIRST-PROCEDURE/FIRST-OBJECT and NEXT-SIBLING pattern.  When dealing with a procedure that was run by another procedure, one can identify the caller procedure with hCalleeProc:INSTANTIATING-PROCEDURE:FILE-NAME if it is still running.


However, if a procedure was persistently run from an ABL class, INSTANTIATING-PROCEDURE can no longer help.  The same problem comes when you want to identify what procedure or class has launched an instance of a class.

The Progress.lang.Object offers a NEXT-SIBLING and PREV-SIBLING property but it does not seem to provide an InstantiatingObject property yet, that would also be required by  procedure object if it was launched from an ABL Object.

At last, the INSTANTIATING-PROCEDURE attribute is also available for low level object types (dyn buffer, dyn temp-table, or GUI widgets).  What if those are created by an ABL class?

Did I miss something in the doc?  Has Progress a plan to offer a facility to manage this kind of situation?

Thanks

/Sébastien

All Replies

Posted by Laura Stern on 12-Oct-2016 08:39

1. I don't know why you're saying that "if a procedure was persistently run from an ABL class, INSTANTIATING-PROCEDURE can no longer help".  INSTANTIATING-PROCEDURE still gives a valid answer for a procedure run persistently.  So I have a feeling I'm misunderstanding what you're saying.

2. We have another way to know the objects/procedures that are leaked and where they were created.  It's called logging.  What we are missing here is a program to read the sometimes lengthy log file to cull out which objects are still around (created but not deleted).  It is not difficult to write this in the ABL.  In fact, someone in tech support recently wrote such a program and we could probably post it somewhere.

3. You can also use the dynamic object tracking feature of the debugger , which is extremely effective if you have a limited scope of code that you think is causing a leak.  

4. Knowing what program created an object is not necessarily tell you who should be deleting it.  But I agree it helps to understand the context of what that proc/object is being used for.

5. We currently have no plans to expand the use of INSTANTIATING-PROCEDURE or something else like it, e.g., for classes.

Posted by Brian K. Maher on 12-Oct-2016 08:46

2. We have another way to know the objects/procedures that are leaked and where they were created.  It's called logging.  What we are missing here is a program to read the sometimes lengthy log file to cull out which objects are still around (created but not deleted).  It is not difficult to write this in the ABL.  In fact, someone in tech support recently wrote such a program and we could probably post it somewhere.

It's already in the KB (see below).  it’s for PASOE but can easily be modified for classic appserver log files.
 

Posted by Frank Meulblok on 13-Oct-2016 04:28

Or slightly older KB article that also relies on logging:

knowledgebase.progress.com/.../P133306

Posted by slacroixak on 13-Oct-2016 08:42

1. Say MyClass.cls does RUN myProc.p persistent.  

In myProc  :

MESSAGE  THIS-PROCEDURE:INSTANTIATING-PROCEDURE VIEW-AS ALERT-BOX.

 => says unknown value

Of course, my point is to query  hproc:INSTANTIATING-PROCEDURE from the outside while walking through the session persistent procedures list.

2. I know logging, and the log-manager.  I use it a lot in dev or test workspaces (I even made a tool to parse it and display a 4GL trace in a treeview with a lot of stuff).   However my goal is to target production to spot parts that fall aside usual tests and just to be on THE real side.  Our App is large (with a few dark corners like all big old apps...) and we have many users at some site, which make constant logging inappropriate.  The utility I am talking about generates some log with the native log-manager and we get those logs.  Perhaps it might become a kind of ProcedureGarbageCollector that may kill the leaked procedures that no longer have a valid instantiating-procedure (cheaper that identifying and curing the offending caller) but then I can have issues with procedures started from class as said in point #1.

3. As said in point 2, my target is production, so no debugger.

4. Indeed, it can help.

5. We deal with a little inconsistency here .  If use only .p's then it is possible to obtain procedure call trees based on the instantiating-procedure attribute.   We try to move progressively** to OO ABL structured code, so still with some .p's... but then we loose the possibility to retrieve how has leaked that proc.

 ** I love this word.  That perhaps how progress should try to be named IMHO.

I would add a 6th point

6. Finally, the instanciating-procedure is a bit poor, and the concerns we had in the past to save CPU cycle and memory look ridiculous today.  A new attribute-property called InstantiatingTrace with the equivalent of PROGRAM-NAME(2) + handle (even a class has one kind of numeric instance id) would help.  This guy would be enabled with a new startup param.  Actually, something like "Procedure <handle> routine" or "<Class type> <kind of instance ID> routine" would be nice.?

Posted by Laura Stern on 13-Oct-2016 09:41

Re #1, I tried this yesterday and again today.  It works just fine for me.  So I don't know what's going on there.

But I still don't understand the larger point.  Yes, knowing the INSTANTIATING-PROCEDURE gives you some context, but again, this doesn't explain why something is leaking.  I presume, the persistent procedure is started up and left running for a reason.  What are the conditions under which it should be shut down?  How do you even know whether any particular procedure should be around at any particular point?  What does any of this have to do with the instantiating procedure?  As I said, the proc that creates something may not be the code responsible for destroying it.  That is the kind of use-case information we would need to know and is entirely missing from this conversation.

Also, this is not information that is available in most programming languages (none that I know of).  Therefore it seems suspect that it should be necessary.

Finally: Generally, tools for finding memory leaks are used during development, not at deployment time.  Yes, I understand that bugs get out there.  But it sounds like this is some regular practice of instrumenting code for finding stray persistent procedures in a deployed application.  Of course, I may be misinterpreting again.

Posted by slacroixak on 14-Oct-2016 07:05

Re #1  I am wondering if we are talking about the same case.  In my tests, hmyProc:INSTANTIATING-PROCEDURE is always unknown if myProc.p was run from an ABL class.  Do you really manage to obtain something else in instantiating-procedure in such a case?

Yes, a parentProc that launches some childProc is not always responsible of destroying it.  But a ChildProc can be launched by many different possible parents, so it does help to find out who has launched it, especially when you find many instances (say tens or hundreds) of a procedure, and top of all when they are launched by some RUN VALUE.

Re #7 "Also, this is not information that is available in most programming languages (none that I know of).  Therefore, it seems suspect that it should be necessary."

=> Other programing languages do not offer elementary constructs like a record buffer or an embedded database engine in the client side to handle temp-tables.  And we see its value

The ABL is a double facet language.  When using only .p’s we are in the script world with surprises at run time.  We *progressively* move to OO with more check at compile time and less surprises at runtime.  In the few (very few) cases that do require a DYNAMIC-NEW(), I can enforce a best practice to always pass the caller object class reference (or the caller procedure handle) to the constructor of the called class so I can find out who has called it later (with interfaces, I can easily make sure I have not missed a case).  On the other hand, it is much harder (even impossible) to refactor all the guys that can possibly called by some RUN VALUE because there is just no way to identify them.  Hence the RunTime tools I need to be efficient: just gather some logs and fix the problems as they get reported, instead of playing with crystal balls or sophisticated tools that may always miss a point.

What is at stake is the “progressively” said above.  ABL developers are expensive.  If Progress wants to help its customer to survive long and well, then perhaps it is worth doing a few constructs that do not exist in other languages.  I could find other related ideas.

In the same area, I believe Progress did a good job to introduce the new error handling with CATCH/THROW etc… so it can be adopted progressively.  At first people did not dare to enable SESSION:ERROR-STACK-TRACE because of its possible impact on performance.  Now we always enable it to get stack traces because the extra CPU resources are worth the efficiency when we investigate an issue.

Perhaps I should enter an ER to have the ability to trace a caller like I said in point #6.

This thread is closed