| 1 |
Preface: |
| 2 |
====== |
| 3 |
You've probably noticed the epic struggle we've had with Amarok 2 |
| 4 |
hanging on exit. After _months_ of tinkering I've now been able to |
| 5 |
identify and fix this issue. This document explains how to prevent |
| 6 |
such issues in the future. |
| 7 |
|
| 8 |
What is a static object? |
| 9 |
================= |
| 10 |
A static object is being initialized on program start, and will only |
| 11 |
become instantiated once. It's conveniently used with the singleton |
| 12 |
design pattern, e.g. in Amarok code. |
| 13 |
|
| 14 |
Example: |
| 15 |
|
| 16 |
static AmarokMenu s_menu; |
| 17 |
|
| 18 |
What is so dangerous about static objects? |
| 19 |
================================ |
| 20 |
A static object's destructor is called _after_ the QApplication |
| 21 |
destructor has been executed. This is fine for plain old datatypes |
| 22 |
(POD) like int, float, and pointers, as they do not have a destructor. |
| 23 |
It's also fine for objects with a trivial destructor that does not |
| 24 |
interfere with the rest of the program. |
| 25 |
|
| 26 |
The danger lies in using static objects that call other parts of the |
| 27 |
application in their destructor. This is e.g. true for most QObjects, |
| 28 |
which rely on the QApplication being intact. If the QApplication is |
| 29 |
destroyed before the static QObject's destructor is run, _bad_ things |
| 30 |
can happen. To name a few: Crashing, hanging, eating live kitten, or |
| 31 |
forcing you to use XMMS. |
| 32 |
|
| 33 |
How can I prevent these problems? |
| 34 |
========================== |
| 35 |
Use K_GLOBAL_STATIC, and use qAddPostRoutine() to ensure that the |
| 36 |
static object's destructor is called when QCoreApplication destructs. |
| 37 |
|
| 38 |
Example: |
| 39 |
|
| 40 |
class AmarokMenu : public QMenu |
| 41 |
{ |
| 42 |
AmarokMenu(); |
| 43 |
}; |
| 44 |
K_GLOBAL_STATIC( AmarokMenu, s_menu ) |
| 45 |
|
| 46 |
AmarokMenu::AmarokMenu() |
| 47 |
{ |
| 48 |
// K_GLOBAL_STATIC is cleaned up *after* Q(Core)Application is gone |
| 49 |
// but we have to cleanup before -> use qAddPostRoutine |
| 50 |
qAddPostRoutine( s_menu.destroy ); |
| 51 |
} |
| 52 |
|
| 53 |
Further reading: |
| 54 |
=========== |
| 55 |
http://api.kde.org/4.0-api/kdelibs-apidocs/kdecore/html/group__KDEMacros.html |
| 56 |
|
| 57 |
|
| 58 |
Thanks for reading, and happy hacking :) |