1. Gastón Clara
  2. PowerBuilder
  3. Thursday, 8 April 2021 10:53 AM UTC

Hi,

Some time ago I needed to implement a auto Log-off (after a certain period of time) functionality on our application. The idea was to close all opened windows, remain on the MDI and display the Log-in window again. With the valuable help of Crhis Pollach I implemented a WindowManager object that helped me to achieve this behavior. Our application is quite big so covering all different scenarios when auto log-off occurs is almost impossible.
Unfortunately we started discovering some issues when response windows were opened and response windows where opened at that time.
What happened is that all windows are closed (including response ones in its parent close event) and log-in window is displayed (another response one). Fine!

But, when the user logs-in back again then errors starts to appear. I found that the issue because of response windows. After I log back again and process all related task for the log-in procedure PB stat processing the remaining code on the parent event where the response window was opened. In most of the cases processing the return value for the response window (that hasn't, as it was programmatically closed) and accessing instance objects and vars that are no longer valid as the window where they were created no longer exists (at least for the user).

I've tryed using Yield and loops with Yield but nothing happens, the behavior continues to be de same.

Is this behavior the expected? Any idea on how to bypass this situations?

Thanks a lot!

Chris Pollach @Appeon Accepted Answer Pending Moderation
  1. Thursday, 8 April 2021 16:47 PM UTC
  2. PowerBuilder
  3. # 1

Hi Gastón;

  When your App performs an Auto Log-Off, I would suggest that it set's a flag for going into this condition. Then when the App is in the process of the Auto Log-Off, all the scripts that process a Close or CloseQuery event ignore their processing so that no Message Box or internal Response dialogues are opened. In my STD Framework I set this "i am in shutdown" condition. If that is the case, then only logging operations are performed when the App is quiesing. I would suggest one more step once the App is basically closed ... use the RESTART() command to make sure all memory is freed and the App instance is properly restarted as a new instance. Food for thought.

Regards ... Chris

Comment
There are no comments made yet.
Gastón Clara Accepted Answer Pending Moderation
  1. Wednesday, 14 April 2021 14:46 PM UTC
  2. PowerBuilder
  3. # 2

Thank you for your answer Chris, but it doesn't exactly reflect what my problem is.

I've attached an image with a call stack. 

If we start from the bottom we can see that we have w_case_record_sup_and_bill that calls n_barcode.of_show_barcode_data_window that opens a response window. We do nothing until applications Idle event is fired. An inactivity message is displayed and then we execute ue_logoff from the MDI frame.

The frame should not be closes but all other opened windows should. So, one of the task of the log of process is to close all opened windows including w_case_record_sup_and_bill. When log-of method finishes we start coming back in the call stack until we reach n_barcode.of_show_barcode_data_window where PB tries to execute the remaining code after opening the response window. What happens here? The application crashes as n_barcode object was previously destroyed when w_case_record_sup_and_bill  was programmatically closed.

My question is, is this the expected behavior? Is there any mechanism that allows us to avoid the execution of code from an object that was previously destroyed?

In this particular example I was able to bypass the situation modifying the return values from the response window and not destroying the n_barcode object when closing its parent window.  But, if this is the only thing that I can do......

Hope that now you better understand what my problem is and once again thank you for your valuable help.

Attachments (1)
Comment
  1. Chris Pollach @Appeon
  2. Wednesday, 14 April 2021 19:39 PM UTC
Hi Gastón;

My STD Framework has an "oe_close_all" event on the "Controller Window" ancestor class (wn_controller_master) that closes all open widows except itself. Again, using the 100% reverse order that any sheet, child, pop-up or response window was opened. The only difference in that logic is that it will *not* close itself. Thus, if the "Controller Window" is an MDI Frame, the last window in your app to remain open would be the MDI Frame (in your example). After that, you could then open the Login window dialogue form the MDI frame again..

Food for thought.

Regards ... Chris

  1. Helpful
  1. Gastón Clara
  2. Thursday, 15 April 2021 07:48 AM UTC
Hi Chris,

My window controller is just a copy of your and it works perfectly. I manage to close all opened windows except from the MDI, display log in window and log user back again. My problem is that after all this, PB starts coming back on the call stack trying to execute the remaining code in all the method from all the objects



In my example (previously attached picture) w_surg_frame is our MDI window.

Execution steps are as follow:



6 - w_surg_frame.ue_log_off()

5 - n_cst_appmanager.of_inactiveapp()

4 - w_idle_warning.timer()

3 - n_barcode.of_show_barcode_data_window()

2 - w_case_record_sup_and_biling.of_process_scanned_item()

1 - w_case_record_sup_and_biling..sle_barcode_modified()



In step 6 all windows are closed, MDI frame remains opened, login window is displayed (response window). After the user types username and password control is returned to the ue_log_off event and continues processing to the end of the method. After that, control passes to step 5 and it processes remaining code on its method, Then to step 4 and do the same. And then to step 3 on n_barcode, and here comes the problem. n_barcode is an instance variable of w_case_record_sup_and_biling, of_show_barcode_data_window was the one that opened the response window and remains waiting there for the response of that window. In a normal situation the user would close the window entering new info or cancelling and we should be able to analyze the result and continue with the process. But in this case there were no user interaction, the window was close programmatically and as the control is returned to this specific step we try to continue doing the same as if it were closed on a "normal" situation.

An here is where the problem is coming, as the object was previously destroyed on step 5 and as we are trying to access properties on that objects but the object no longer exists, the application crashes (null exception).



Summarizing, when processing the call stack in reverse order PB is trying to access objects that were already destroyed by the log-off process.

Assuming that this is the way PB works my question is, is there any "generic" solution in order to avoid this behavior?

I know that it can be controlled by adding code on the methods that opens response windows, but the thin is that my app has around 500 response windows. Modifying all calling methods and testing would be challenging and loooong.



Sorry for the long descriptions and thank you for your help.

  1. Helpful
  1. Chris Pollach @Appeon
  2. Thursday, 15 April 2021 16:59 PM UTC
Hi Gastón;

Yes, this sounds very strange indeed! However, it could be a side effect of the way your App is designed. I am still wondering if you need a Flag that states you are closing everything and not to process any logic in any of the open window's Close or Close Query events like my framework does. Also, I would still recommend a Restart() if you want to avoid your App wows and make sure that all resources are cleaned up for the new login. Also, the restart approach would prevent you from modifying all your response window code. Just a thought.

Regards ... Chris
  1. Helpful
There are no comments made yet.
Olan Knight Accepted Answer Pending Moderation
  1. Wednesday, 14 April 2021 15:14 PM UTC
  2. PowerBuilder
  3. # 3

Maybe I don't understand the issue, but from what I read it seems to me that the answer to your problem is to validate any object prior to trying to close it or work with it:

IF (NOT (IsNull (w_sheet_1)) AND (IsValid (w_sheet_1)) THEN
   Close (w_sheet_1)
END IF

Apologies if I've missed the actual issue.


Later -

Olan

 

Comment
  1. Gastón Clara
  2. Wednesday, 14 April 2021 15:18 PM UTC
Unfortunately the problem is not to close the that task is correctly done, what happens is that after having closed the window PB continues processing the code that opened a response window even when I programmatically destroyed it.
  1. Helpful
  1. Olan Knight
  2. Wednesday, 14 April 2021 15:20 PM UTC
Use the same idea: test to see if the window exists and is valid BEFORE running that code.
  1. Helpful
There are no comments made yet.
  • Page :
  • 1


There are no replies made for this question yet.
However, you are not allowed to reply to this question.