Under some circumstances ** I'd like a traditional (non PAS-OE yet) StateFree AppServer agent quit its session from the ABL code of its deactivate procedure.
** for cleanup purposes, like when this agent finds out some bad code has left some unwanted share-lock records during a hit.
First I tried with a simple QUIT as the doc says the following about the QUIT Statement:
When QUIT is executed from within a procedure running on an AppServer, it terminates the ABL session running on the AppServer, causing the AppServer agent to shut down and returns to the ABL client session from which it was spawned.
But obviously it does not work, as I can still see some record locks from persistent procedures that I started intentionally (for the sake of the test) during the AppServer Hit.
So at the end of the day, I made a work around by firing an OS-COMMAND with asbman -i <AS-name> -stopagent <pid>
I do not like this solution because it may take too long before the asbman -stopagent gets its job done, so the agent may run other requests.
The doc also says the following about PAS-OE:
When QUIT is executed from within a procedure running on a Pacific Application Server for OpenEdge (PAS for OE), the ABL session is reset to its initial state, which includes deletion of persistent procedures and static ABL objects, the disconnection of databases (or re-connection if the databases were connected at startup), and the clean-up of all global data, such as shared variables. Control then returns to the ABL client session from which the server session was accessed, and the server session is returned to its PAS for OE session pool for access by other client requests.
This sounds promising. But I'd like to be sure this kind cannot be achieved with a Statefree traditional AppServer. I was told the QUIT does what I wish for the stateless operating mode (it would even quit the agent process), but I am at statefree.
function reallyQuit returns logical ():
What do you "really" mean Stefan ? Anything logical that I missed ?
The recursive function call will blow up the stack and kill the agent.
Nice one Stefan! Never let the ABL tell you you cannot do something ;-)
I have experimented in the past with calling the exit() function from libc for the same use case but never trusted I could safely call it with db's connected. This one happens from time to time due to developer error so it's probably relatively safe (other than maybe leaving some temp files behind and causing a short cpu spike.)
Hi Stefan, thanks you for your input. I just gave it a try. This method sound amazing but cause two problems:
1) it inserts about 1500 lines in the agent log file to show the terrible offending callstack .
2) It raises Progress.Lang.SysError on the client side saying "Server Terminated Unexpectedly". Perhaps I could manage to catch it an decide to ignore it, but if I get this kind of unexpected error for another reason, then I will miss it :(
doing a hara-kiri with an OS-COMMAND kill <yourOwnPid> leads to about the same result, but without the issue in the log
I wish there would be a way to achieve a nice exit quit, an move the agent outside of the pool so it cannot process any other request.
Any opinion from PSC people?
1. not sure what you have enabled to get a 1500 line callstack, I just get a clean
[18/12/07@18:20:45.138+0100] P-028300 T-017928 1 AS -- Exact Financials 7.25.03 - AppServer started. 188.8.131.52.1429
[18/12/07@18:20:45.138+0100] P-028300 T-017928 1 AS -- ** ABL Debug-Alert Stack Trace **
[18/12/07@18:20:45.138+0100] P-028300 T-017928 1 AS -- --> system/start/appstart.p at line 12661 (..\..\..\build\oe11.7\bl\progress\system\start\appstart.r)
[18/12/07@18:20:52.836+0100] P-022220 T-027132 1 AS -- (Procedure: 'terminateAgent finance/ifallgen/gmcomp.p' Line:14431) HandleAction: bye bye, terminating agent.
The message is given by the function on the /first/ call.
2. a quit would also have triggered something that your client would need to deal with.
Hi Brian, I know my very first post is a bit long. It was already saying my current work around is an OS-COMMAND asbman -i <AsName> -stopagent <hisPid> ;)
I have it running in production, and for one case my agent has run 2757 more hits before the asbman -agentstop completed its job :( (actually, it even fired that asbman command 2757 times... I've just changed the code with a new global share var to limit to one single call). So 2757 opportunities to cause a problem.
Brian, I believe we need a may to make an agent tell its broker "Huston I have a problem, please remove me from the agent pool NOW and shut me down, as I must no longer process any more request"
I know the PASOE offers many nice REST management API's. Is it possible to fire such a remove me from the pool synchronously? I mean, for some points, the guy that should trigger this action is the agent itself.
Stefan, thank you again for your post.
1. It may depend on my logmanager setting. I have the 4GLMessage:4 so an unexpected error shows in the log with its call stack, which may explain that.
2. I agree with you for point. For now, I believe we might need something new, as said in my post to Brian.
There is this:
PROCEDURE exit EXTERNAL '/usr/lib/libc.a(shr_64.o)' CDECL PERSISTENT.
def input param iexit as long no-undo.
You will want to first stop all persistent procedures and disconnect all db's. I do not know though what happens if you do this and you have static classes in memory with that refer to db's connected with shared memory connections.
'/usr/lib/libc.a(shr_64.o)' is probably the AIX path, on centos/redhat 7 it's '/lib64/libc.so.6' I believe.
Jankeir, so far, we target mainly Windows. That being said, even if I find a way to fire an exit(0) on Windows, I fear it may send a Progress.Lang.SysError on the client side saying "Server Terminated Unexpectedly". Obviously, the QUIT statement was designed to exit gracefully for some operating mode, and not for others. I also wanted to point out the need to trigger a graceful exit from the ApServer deactivate procedure.
You have my vote if you enter a feature request .
Would it make sense to use a FINALLY clause to ensure that resources (such as persistent procedures) are properly cleaned out?