Subscribe for automatic updates: RSS icon RSS

Login icon Sign in for full access | Help icon Help
Advanced search

Pages: [1]
  Reply  |  Print  
Author Topic: GAS and SSO License usage  (Read 10546 times)
Jos? V.
Posts: 58


« on: April 29, 2021, 05:05:06 pm »

Hello,

Im currently setting up a delegate SSO service for the apps running under GAS(currently using httpdispatch).

I used the example on https://github.com/FourjsGenero/ex_simplesso as a base for my SSO and it is currently working fine except for the license usage.

When I launch and app with the delegate setup on the configuration file the SSO presents the login page and launches a DVM that consumes a license.
If I authenticate correctly the app is launched and a second license is consumed until that user leaves the app and the license is released.
The delegate service keeps the license and If I try to access it again it will not consume a second license. This is OK and expectable.

The problem is that when I close the browser window while on the SSO login page, or the SSO service for some reason gives me an internal error(not authentication error) the license goes to a "zombie" state and is never released.
If I then try to launch another app, another instance of the SSO is launched and another license is consumed.

So I read the manual and setup <TIMEOUT><KEEP_ALIVE> tags to kill the DVM when not in use as this seems to be the solution but it didn't solve my problem.
Am I doing this wrong? How can I release these licenses without using flmprg?

My app xcf is as follows:
Quote
<APPLICATION Parent="defaultgwc">
<.........>
        <PATH>$(res.ldbasepath)bin</PATH>
        <DVM>/usr/local/bin/bash</DVM>
        <MODULE>opMassivas</MODULE>
        <PARAMETERS>
            <PARAMETER> $(application.start.uri) </PARAMETER>
        </PARAMETERS>
        <DELEGATE service="ssoServiceProvider"/>
    </EXECUTION>
    <UA_OUTPUT>
        <PROXY>$(res.uaproxy.cmd)</PROXY>
        <PUBLIC_IMAGEPATH>$(res.public.resources)</PUBLIC_IMAGEPATH>
    </UA_OUTPUT>
</APPLICATION>


And the delegate service xcf:
Quote
<APPLICATION Parent="ws.default">
<.....>
        <PATH>$(res.ldbasepath)bin</PATH>
        <DVM>/usr/local/bin/bash</DVM>
        <MODULE>singleSSO</MODULE>
        <PARAMETERS>
            <PARAMETER> $(application.start.uri) </PARAMETER>
        </PARAMETERS>
        <POOL>
            <START>0</START>
            <MIN_AVAILABLE>0</MIN_AVAILABLE>
            <MAX_AVAILABLE>1</MAX_AVAILABLE>
        </POOL>
    </EXECUTION>
    <TIMEOUT>
        <DVM_AVAILABLE>10</DVM_AVAILABLE>
        <KEEP_ALIVE>240</KEEP_ALIVE>
        <REQUEST_RESULT>60</REQUEST_RESULT>
    </TIMEOUT>
</APPLICATION>
Reuben B.
Four Js
Posts: 1116


« Reply #1 on: April 30, 2021, 02:27:04 am »

A license is freed up when the program exits normally through END MAIN or EXIT PROGRAM.

If a program exits abnormally i.e crashes, then it will continue to consume a license until the license check process occurs.  This occurs periodically but can be forced to occur with ...
https://4js.com/online_documentation/fjs-genero-manual-install-html/#genero-install-topics/t_license_controller_force_check.html
https://4js.com/online_documentation/fjs-genero-manual-install-html/#genero-install-topics/t_flm_force_user_list_check.html

How the license check works is that when a license is consumed the process id (pid) is recorded.  If you look in fglWrt -a info users, you will see the pid.  The license check process looks to see if that pid is still in use by the operating system.  if it isn't then it knows it can free up that license.  If that pid is in use then it won't free up that license.

If the process consuming a license is in some form of infinite loop, then the license check process is going to see that it is still running and so not free up that license.

You have checked KEEP_ALIVE which is good.  However you said "So I read the manual and setup <TIMEOUT><KEEP_ALIVE> tags to kill the DVM ".  Note the documentation  http://4js.com/online_documentation/fjs-gas-manual-html/#gas-topics/c_gas_asref_APPLICATION_TIMEOUT_KEEP_ALIVE.html, refers to proxy not to the DVM.  KEEP_ALIVE will stop the proxy, the proxy in turn will then send a signal to its child fglrun processes. 

When the proxy sends this signal, the Web Service Server program should capture that and exit the program thus freeing up that license.  This is the 15575 referred to here http://4js.com/online_documentation/fjs-fgl-manual-html/#fgl-topics/c_gws_ComWebServiceEngine_GetHTTPServiceRequest.html.  If this Web Service server program is stuck in a loop, then it is feasible that the com.WebServiceEngine.getHTTPServiceRequest is never being executed and so the signal is not acted upon.  The other potential gotcha is that the WHILE LOOP doesn't exit if 15575 occurs.

if something like this is happening, the clues will be at the end of the gwsproxy log.  You should see after 240 seconds of inactivity, messages indicating that KEEP_ALIVE is triggered and the proxy is shutting down.

So I would turn on ALL debugging in the  logs, look at the end of gwsproxy logs to verify what you think is happening, and try and determine what state the fglrun program is in.  Is it in an infinite loop, or is it waiting to process next com.WebServiceEngine.getHTTPServiceRequest and is it exiting when the proxy tells it to shut down.

Reuben



 




Product Consultant (Asia Pacific)
Developer Relations Manager (Worldwide)
Author of https://4js.com/ask-reuben
Contributor to https://github.com/FourjsGenero
Jos? V.
Posts: 58


« Reply #2 on: April 30, 2021, 10:45:38 am »

Thanks for the help Ruben.
You were very clear as always!

I checked that my program is in a while loop but a try/catch block is in place and exits the while when it receives the -15575.
I can see this in the vm logs clearly for every "stuck" PID:
Quote
#
#Date: 2021/04/29 16:11:30.891069
#PID: 30605458
#
Access (10.10.21.70):incoming request : /ws/r/ssoServiceProvider/Delegate
DoDelegate : originURL=http://apaxsys004:6394/ua/r/opMassivasL
ERROR :      -15575

My code goes like this:
Quote
    call com.WebServiceEngine.Start()

    while TRUE
        try
            let req =
                com.WebServiceEngine.GetHttpServiceRequest(3600)
    (......)
        catch
            display "ERROR : ", STATUS
            exit while
            end try
    end while

As you can see the display at the catch block is the same as the vm log. Also, the PID does not exist anymore, the process already died(ps -ef | grep 30605458 returns nothing)

As for the fglWrt command it has a weird behaviour.
When I run "fglWrt -u all" or "fglWrt -a info users" on the machine that ran the process I get no results.

But when I run it on the machine that host the license manager I get the following:
Quote
Product      : Four Js Dynamic Virtual Machine
Type         : Runtime version
Users        : 4/4
Host         : apaxsys004
    Process Id 23593196
            Process Id 30605458
            Process Id 14090484

As you can see the PID 30605458 is there and the host that launched it is in fact apaxsys004.
These PIDs do not exist either on the FLM server machine or on the Host machine and running flmprg -u all or flmprg -u apaxsys004 does not clear them.

Is this due to having FLM and GAS on diferent machines? You said that the licence check process looks to see if the pid exists, but how does he do this if the process is on a remote machine?


Reuben B.
Four Js
Posts: 1116


« Reply #3 on: May 03, 2021, 01:52:47 am »

Quote
is this due to having FLM and GAS on different machines? You said that the licence check process looks to see if the pid exists, but how does he do this if the process is on a remote machine?

You said GAS, GAS is irrelevant for licensing, perhaps you meant FGL.

If so your question is a good one, and the answer lies in the second sentence here
https://4js.com/online_documentation/fjs-genero-manual-install-html/#genero-install-topics/t_flm_force_user_list_check.html

Quote
The synchronization will be done at the next dialogue between the license controller of the machine and the Four Js License Manager.

I'd probably use the word "communication" instead of "dialogue"  flmprg -u... , won't run the licence check process straight away.  It effectively sets an internal flag inside FLM and the next time that the license controller communicates with FLM, it will do that check then. 

The other thing to note to aid the understanding of the above is to know what the license controller is.  With FLM, you have FLMDIR/bin/flmprg.  If you look at FGL you have FGLDIR/bin/fglWrt.  fglWrt is known as the License Controller.

When fglrun executes (or fglcomp compiles), it calls its fglWrt to check the license.  fglWrt reads its FGLPROFILE and if it detects FLM is in use, it will communicate with FLMDIR/bin/flmprg that is running on the server and port as indicated by values in FGLPROFILE.

So after running flmprg -u, flmprg sets an internal flag so that next time fglWrt communicates with flmprg from a remote server, it indicates to that fglWrt that it needs to effectively run "fglWrt -a ps" on that remote server and return the results to flmprg so that it see if it can free up the license.

So don't execute

flmprg -a info users
flmprg -u all
flmprg -a info users

and expect to see an immediate result.  You have to do something like

flmprg -a info users
flmprg -u all
Start a Genero program on the remote server
flmprg -a info users

You also said ...

Quote
When I run "fglWrt -u all" or "fglWrt -a info users" on the machine that ran the process I get no results.
... take care wether you are running flmprg or fglWrt.  When using FLM, I would expect you to be using flmprg -u all, flmprg -a info users,  on the server where FLM is running. 

The final place where things go wrong. FLMDIR/bin/flmprg, FGLDIR/bin/fglWrt are communicating with each other.  Are they communicating in a way where there is 100% clarity in what they are communicating to each other, i.e check their versions flmprg -V and fglWrt -V.  Ideally they return the same version number but when they don't there can be that nagging doubt, is it not working properly because there was a change between the versions?  More so if there is a big difference e..g 5.20.17 <--> 5.20.16 is probably ok but 5.19.10 <--> 5.20.16 is not.

If you need support to help, you will need to give them info such as

FLMDIR server e.g. ?????
FLMDIR value e.g. /opt/fourjs/flm/5.20.17
FLMDIR version e.g. 5.20.19
lmprofile file


FGL server e.g. apaxsys004
FGLDIR value e.g /opt/fourjs/fgl/3.20.16
FGLDIR version e.g. 3.20.16
fglWrt version e.g. 5.20.17
fglprofile file

and they may ask you to record a log of the communication that is taking place between fglWrt and fglWrt.

Hope that helps

Reuben

PS You have process id greater than 32767.  How many lines of output is fglWrt -a ps on the remote server















Product Consultant (Asia Pacific)
Developer Relations Manager (Worldwide)
Author of https://4js.com/ask-reuben
Contributor to https://github.com/FourjsGenero
Jos? V.
Posts: 58


« Reply #4 on: May 11, 2021, 04:16:26 pm »

In the process of making a small standalone service to showcase the licensing error to the support team I managed to figure out the problem.

The issue was that I was using “defer interrupt” and “defer quit” instructions on the main 4gl.
These instructions are standard for our legacy 4gl terminal applications and they carried over to our new code.

Apparently using “defer interrupt” and “defer quit” prevents the license check although the -15575 exception is raised and the PID terminated.

As far as we are concerned the issue is solved since we do not need those instructions on the delegate login service or any other service.

Thank you for your help Reuben
Reuben B.
Four Js
Posts: 1116


« Reply #5 on: May 12, 2021, 12:51:30 am »

Hi,

Thanks, it is always appreciated when we get an explanation when issues are resolved.

Quote
Apparently using “defer interrupt” and “defer quit” prevents the license check although the -15575 exception is raised and the PID terminated.

However I am not 100% convinced by the explanation.  My initial thoughts (without creating an example to verify) are that defer interrupt might prevent the PID termination, but should not interfere with the license check.  However I wonder if there was some other code around your "defer interrupt" such as "options input wrap" or "options field order form" ? (they tend to get placed in the same initialisation function).

Reason I think of that is if you study

Code
  1. MAIN
  2.  
  3.    RUN "fglWrt -a info users | grep 'Users'"
  4.  
  5.    DEFER INTERRUPT
  6.    RUN "fglWrt -a info users | grep 'Users'"
  7.  
  8.    OPTIONS INPUT WRAP
  9.    RUN "fglWrt -a info users | grep 'Users'"
  10.  
  11.    MENU ""
  12.        BEFORE MENU
  13.           RUN "fglWrt -a info users | grep 'Users'"
  14.        ON ACTION exit
  15.            EXIT MENU
  16.    END MENU
  17. END MAIN

you will see that some code that requires GUI such as OPTIONS INPUT WRAP triggers consumption of the license. 

and there is a recent support case where someone put there web service server code in a GUI program similar to ...

Code
  1. MENU ""
  2.   ON ACTION start
  3.      CALL call com.WebServiceEngine.Start()

... and is querying the license consumption and it was not freed up as expected, and so I am wondering if there is something we have not catered for in that we are expecting a program to be GUI or a Web Service, but not both...

Reuben

Product Consultant (Asia Pacific)
Developer Relations Manager (Worldwide)
Author of https://4js.com/ask-reuben
Contributor to https://github.com/FourjsGenero
Jos? V.
Posts: 58


« Reply #6 on: May 12, 2021, 10:09:55 am »

You are right.
I was not giving much credit to "options input wrap" but I did remove that one too as it made no sense on a webservice with no GUI other than xhtml.
The only 3 lines edited in my code where in fact:
Quote
defer interrupt
defer quit
options input wrap

Pages: [1]
  Reply  |  Print  
 
Jump to:  

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines