FoxInCloud
form QueryUnload event
Gravatar is a globally recognized avatar based on your email address. form QueryUnload event
  Paul
  All
  Jan 23, 2019 @ 08:24pm

Hi,

Is it normal for the QueryUnload event of a form to be executed when the WC server is shut down?

What I am seeing is that after I click the Exit button in the WC status window and the wait window "Awsets.Destroy() is restoring your interactive environment..." appears, the QueryUnload code is executed.
This is a problem for two reasons :

  1. by that stage the initial procedure, classlib and other settings have been restored to the pre-application state and the QueryUnload code crashes since it relies on these
  2. it doesn't make sense anyway, there is no user interaction driving the "closing" of the form

Am I doing something wrong?

Thanks
Paul

Gravatar is a globally recognized avatar based on your email address. re: form QueryUnload event
  FoxInCloud Support - Thierry N.
  Paul
  Jan 24, 2019 @ 03:09am

Hi Paul,

Not the designed behavior; when clicking the 'exit button':

procedure cmdExit.Click
…
CLEAR EVENTS
…

procedure awStart
…
READ EVENTS
…
release goWCserver
…

procedure awServer.destroy
…
this.oAppHost.cleanUp
…

procedure awAppHost.cleanUp
…
for each loForm in _screen.Forms foxobject
  m.loForm.release
endfor
…
this.oAppSets = .null. && releases the config object, thus restoring the IDE
…
  1. FoxInCloud .release() the forms BEFORE restoring the environment
  2. from VFP doc:

The QueryUnload event does not occur if you issue the RELEASE command on the form in code or invoke the form's Release method.
The QueryUnload event occurs when CLEAR WINDOWS, RELEASE WINDOWS, or QUIT is executed in code, or when the user double-clicks the window pop-up menu icon or chooses Close from the window pop-up menu on a form.

Nowhere does FoxInCloud execute CLEAR WINDOWS or RELEASE WINDOWS

Here is what I understand:

  1. for some reason (eg. a missing dodefault(), a wrong nodefault or a dangling form object reference), some forms fail to .release()
  2. xxxSets.destroy() somehow executes a CLEAR WINDOWS or RELEASE WINDOWS

Please set a breakpoint in some form.queryUnload() and post the call stack.

Gravatar is a globally recognized avatar based on your email address. re: form QueryUnload event
  Paul
  FoxInCloud Support - Thierry N.
  Jan 24, 2019 @ 07:56pm

While debugging I see that thisform.ReleaseType = 1.

I'm not seeing any clear windows or release windows code, so I don't know why the QueryUnload is being called.
Incidentally, I tried putting some code in the QueryUnload of another form and when WC is shut down that code is not executed. .
.
.
p.s. after I run the section of our application that may, or may not, open the problematic form and then shut down WC and then try to run sfictest.prg afterwards I get this error :

I have to "Restore Environment" from the FoxInCloud menu to make things work again.
I do not get this behaviour if I run the section of our application that is not related to the problematic form. I haven't yet found a difference that would account for this, but something odd is happening...

Paul

Paul

Gravatar is a globally recognized avatar based on your email address. re: form QueryUnload event
  FoxInCloud Support - Thierry N.
  Paul
  Jan 25, 2019 @ 01:26am

OK, got it, thanks for the details (always need detailed code and screenshots to understand a bug)

awStart() does not have a clear windows, but has a clear all which triggers a clear windows, hence the issue you have.

Because clear all fails you have the second issue.

We need to understand why stockControlCheckArea.release() fails when awAppHost.cleanUp() calls it (see the call stack in my earlier post).

Some possible hints:

  • another form stores a reference to the stockControlCheckArea form or one of its member, in which case you'd need to sub-class awAppHost and override .cleanUp() to release the forms in order of dependencies (will explain later how to do that if you're in this case)
  • stockControlCheckArea runs in a private datasession and one buffered alias is dirty (FWIW awFrm.destroy() cleans up dirty buffers, you may want to add a dodefault())

Note: this issue is strictly limited to the development phase; when stopping a production server running in COM mode (standard practice), the server dll kills the COM process and/or handles the shutdown errors.

Gravatar is a globally recognized avatar based on your email address. re: form QueryUnload event
  Paul
  FoxInCloud Support - Thierry N.
  Jan 29, 2019 @ 04:08pm

I found the problem - I have a global object that is keeping references to open forms and the references weren't always being nulled when a form closes.
Easy fix, so I thought; put some code in the form's Release method to clear the reference. This works fine in lan mode, but in web mode the code was not being executed when a form is being released from awAppHost.cleanUp (I don't have the code for this so I cannot debug it, but my set step on in the Release method of my form was never called). I don't understand why the code was not being run.
The side effect, as we found, is that the QueryUnload is later executed.

Anyway, I have simply made the global object reference stuff lan-mode-only and that has made the problem go away. It probably doesn't make too much sense in web mode in any case, where forms are initialised and left open for the lifetime of the server.

Paul

Gravatar is a globally recognized avatar based on your email address. re: form QueryUnload event
  FoxInCloud Support - Thierry N.
  Paul
  Jan 29, 2019 @ 11:57pm

the Release method of my form was never called

Interesting feedback, thanks

Will double check this shutdown procedure
(quite complex to be honest, took a long time to set up because of the internal object cross-references)

Not sure why you would hold a reference to open forms while _screen.forms does exactly the same.

Does form.release() execute after you remove your form reference?

© 1996-2019