Originally posted by ttheoria
I spent hours trying to debug a multiview application, before I understand that I don't get the same error depending on where/how I start the script.
For example, run the example script SMS_example.py:
1) on the phone, start script sms_example.py, then exit the app, and exit python. All is fine
2) on the phone, start the bt_console, and on the desktop hyperterminal, launch the application: execfile('e:\\system\\apps\\python\\my\\SMS_example.py')
Then exit the app, exit python ==> Kern-EXEC 3 (app closed python)
Unable to reproduce this on a 6630. Which phone do you have?
3) on the emulator, start the script SMS_example.py, exit the app, exit python ==> CONE 8 error
CONE8 says that windows resources are not freed. The simplest multiview app I've made would still generate error. Is it important? Anybody knows whether something's wrong with the sms example script?
Yes, at least two things:
The SMS example script makes reference cycles that it doesn't break
and since Python for Series 60 Release 1.0 doesn't have support for
collecting cyclic garbage the end result is that all resources are not
freed properly at application exit. Apparently that script was never
tested in the emulator and so we missed this.
In the example application the reference cycles are created between
SMS_multiviewApp and the view objects, and between the view objects
and their UI widgets (when you say self.handle_select the interpreter
creates behind the scenes a bound function object that contains a
reference to self). The native resources that don't get freed are the
UI widgets and the Ao_lock inside SMS_multiviewapp.
There are two ways to deal with the situation:
- break reference cycles between objects so that they get garbage
collected normally and their members are thus freed implicitly,
- add a "destructor method" to each object that may become a part of a
reference cycle that breaks references to native resources that the
object owns.
The latter option is probably better, since trying to break all
reference cycles between an arbitrary set of complex Python objects is
hard. So, in terms of code this means that you should add to each view
a close() method that removes the reference to the UI widget that the
view owns, e.g.:
Code:
def close(self):
del self.numbers_list
...and add to SMS_multiviewApp.close() code that calls those view
close() methods and breaks the reference to the Ao_lock owned by the
SMS_multiviewApp object:
Code:
def close(self):
[...]
for x in self.views:
x.close()
del self.lock
Some reminders are in order here: Remember that in Python, "del
someobject" only removes the given reference from a namespace. This
results in the deallocation of the object _only_ if there are no more
references to it. Another thing to remember is that Python does _not_
guarantee that __del__ methods are called for objects that still exist
at the time the interpreter exits, so unfortunately the simple
solution of breaking cycles in the __del__ method is not foolproof.
A smaller problem with the script is that it doesn't restore
appuifw.app.exit_key_handler properly. A well-behaved application
should save the value of exit_key_handler at startup and restore it
before it exits.