Bug 338176 - Face Recognition memory allocation crash application
Summary: Face Recognition memory allocation crash application
Status: RESOLVED FIXED
Alias: None
Product: digikam
Classification: Unclassified
Component: Faces-Recognition (show other bugs)
Version: 4.4.0
Platform: Compiled Sources Linux
: NOR crash (vote)
Target Milestone: ---
Assignee: Digikam Developers
URL:
Keywords: drkonqi
Depends on:
Blocks:
 
Reported: 2014-08-10 16:16 UTC by Christian
Modified: 2017-07-26 18:07 UTC (History)
19 users (show)

See Also:
Latest Commit:
Version Fixed In: 4.9.0


Attachments
valgrind output (end of it) (90.78 KB, text/plain)
2014-11-03 04:39 UTC, Christian
Details
Another valgrind output (28.11 KB, text/plain)
2014-11-06 05:49 UTC, Christian
Details
digikam valgrind memory leak trace (17.20 KB, text/plain)
2015-03-06 09:01 UTC, wwdiver
Details
start of digikam 4.8.0 on opensuse 13.1 (89.75 KB, text/plain)
2015-03-18 10:26 UTC, Johannes
Details
libkface.patch (733 bytes, patch)
2015-03-20 20:20 UTC, Maik Qualmann
Details
valgrind output (339.04 KB, application/zip)
2015-03-21 19:04 UTC, Stephan Olbrich
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Christian 2014-08-10 16:16:28 UTC
Application: digikam (4.2.0)
KDE Platform Version: 4.12.5 (Compiled from sources)
Qt Version: 4.8.5
Operating System: Linux 3.14.14-gentoo x86_64
Distribution: "Gentoo Base System release 2.2"

-- Information about the crash:
- What I was doing when the application crashed:
Click on the "Recognise faces" for "Skip pictures that have been scanned", and then start the recognising process.
It runs quickly up to some % but then stops. Digikam doesn't hang, but the system becomes sluggish. I think it's running out of memory.
At the moment it always stops at 12%. But earlier, it has been working fine. (The action that caused it to fail now may be that I have imported and "found faces" in a few more albums.) The problem seems to be in face recognition, as face finding has worked fine.
Based on the trace, I am marking this as a possible duplicate of another bug, but note that my experience concerns version 4.2.0 on linux.

The crash can be reproduced sometimes.

-- Backtrace:
Application: digiKam (digikam), signal: Aborted
Using host libthread_db library "/lib64/libthread_db.so.1".
pthread_cond_wait () at ../nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S:185
[Current thread is 1 (Thread 0x7f2592a77840 (LWP 24459))]

Thread 5 (Thread 0x7f256f985700 (LWP 24464)):
#0  pthread_cond_wait () at ../nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S:185
#1  0x00007f258c8c0873 in wait (time=18446744073709551615, this=0x2260890) at thread/qwaitcondition_unix.cpp:86
#2  QWaitCondition::wait (this=this@entry=0x2266440, mutex=mutex@entry=0x2266438, time=time@entry=18446744073709551615) at thread/qwaitcondition_unix.cpp:158
#3  0x00000000005fa879 in Digikam::ScanController::run (this=0x2134f70) at /portage_builddir/portage/media-gfx/digikam-4.2.0/work/digikam-4.2.0/core/digikam/database/scancontroller.cpp:725
#4  0x00007f258c8c02dc in QThreadPrivate::start (arg=0x2134f70) at thread/qthread_unix.cpp:338
#5  0x00007f2589a172da in start_thread (arg=0x7f256f985700) at pthread_create.c:309
#6  0x00007f258badc32d in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:111

Thread 4 (Thread 0x7f256f184700 (LWP 24465)):
#0  0x00007f2584c7dcea in g_mutex_get_impl (mutex=0x7f25600009a0) at /portage_builddir/portage/dev-libs/glib-2.40.0-r1/work/glib-2.40.0/glib/gthread-posix.c:120
#1  0x00007f2584c7dfe9 in g_mutex_unlock (mutex=mutex@entry=0x7f25600009a0) at /portage_builddir/portage/dev-libs/glib-2.40.0-r1/work/glib-2.40.0/glib/gthread-posix.c:228
#2  0x00007f2584c3b6da in g_main_context_prepare (context=context@entry=0x7f25600009a0, priority=priority@entry=0x7f256f183c18) at /portage_builddir/portage/dev-libs/glib-2.40.0-r1/work/glib-2.40.0/glib/gmain.c:3417
#3  0x00007f2584c3be3e in g_main_context_iterate (context=context@entry=0x7f25600009a0, block=block@entry=1, dispatch=dispatch@entry=1, self=<optimized out>) at /portage_builddir/portage/dev-libs/glib-2.40.0-r1/work/glib-2.40.0/glib/gmain.c:3714
#4  0x00007f2584c3c04c in g_main_context_iteration (context=0x7f25600009a0, may_block=1) at /portage_builddir/portage/dev-libs/glib-2.40.0-r1/work/glib-2.40.0/glib/gmain.c:3795
#5  0x00007f258c9eb8ee in QEventDispatcherGlib::processEvents (this=0x7f25600008c0, flags=...) at kernel/qeventdispatcher_glib.cpp:452
#6  0x00007f258c9bba2f in QEventLoop::processEvents (this=this@entry=0x7f256f183d80, flags=...) at kernel/qeventloop.cpp:149
#7  0x00007f258c9bbd10 in QEventLoop::exec (this=this@entry=0x7f256f183d80, flags=...) at kernel/qeventloop.cpp:204
#8  0x00007f258c8bdb80 in QThread::exec (this=this@entry=0x21b7390) at thread/qthread.cpp:536
#9  0x00007f258c99d85f in QInotifyFileSystemWatcherEngine::run (this=0x21b7390) at io/qfilesystemwatcher_inotify.cpp:256
#10 0x00007f258c8c02dc in QThreadPrivate::start (arg=0x21b7390) at thread/qthread_unix.cpp:338
#11 0x00007f2589a172da in start_thread (arg=0x7f256f184700) at pthread_create.c:309
#12 0x00007f258badc32d in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:111

Thread 3 (Thread 0x7f2535ffb700 (LWP 24496)):
[KCrash Handler]
#6  0x00007f258ba26bf5 in __GI_raise (sig=sig@entry=6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:56
#7  0x00007f258ba28067 in __GI_abort () at abort.c:89
#8  0x00007f258c31ae05 in __gnu_cxx::__verbose_terminate_handler () at /tmp/portage/sys-devel/gcc-4.7.3-r1/work/gcc-4.7.3/libstdc++-v3/libsupc++/vterminate.cc:95
#9  0x00007f258c318ec6 in __cxxabiv1::__terminate (handler=<optimized out>) at /tmp/portage/sys-devel/gcc-4.7.3-r1/work/gcc-4.7.3/libstdc++-v3/libsupc++/eh_terminate.cc:40
#10 0x00007f258c318ef3 in std::terminate () at /tmp/portage/sys-devel/gcc-4.7.3-r1/work/gcc-4.7.3/libstdc++-v3/libsupc++/eh_terminate.cc:50
#11 0x00007f258c3191c5 in __cxxabiv1::__cxa_rethrow () at /tmp/portage/sys-devel/gcc-4.7.3-r1/work/gcc-4.7.3/libstdc++-v3/libsupc++/eh_throw.cc:116
#12 0x00007f258c8b3f6d in QThreadPoolThread::run (this=0x4e65750) at concurrent/qthreadpool.cpp:114
#13 0x00007f258c8c02dc in QThreadPrivate::start (arg=0x4e65750) at thread/qthread_unix.cpp:338
#14 0x00007f2589a172da in start_thread (arg=0x7f2535ffb700) at pthread_create.c:309
#15 0x00007f258badc32d in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:111

Thread 2 (Thread 0x7f25197fa700 (LWP 24504)):
#0  0x00007f2589a19877 in __GI___pthread_mutex_lock (mutex=0x7f25680998f0) at ../nptl/pthread_mutex_lock.c:125
#1  0x00007f2584c7dfb1 in g_mutex_lock (mutex=<optimized out>) at /portage_builddir/portage/dev-libs/glib-2.40.0-r1/work/glib-2.40.0/glib/gthread-posix.c:209
#2  0x00007f2584c3be15 in g_main_context_iterate (context=context@entry=0x7f2568099500, block=block@entry=1, dispatch=dispatch@entry=1, self=<optimized out>) at /portage_builddir/portage/dev-libs/glib-2.40.0-r1/work/glib-2.40.0/glib/gmain.c:3701
#3  0x00007f2584c3c04c in g_main_context_iteration (context=0x7f2568099500, may_block=1) at /portage_builddir/portage/dev-libs/glib-2.40.0-r1/work/glib-2.40.0/glib/gmain.c:3795
#4  0x00007f258c9eb8ee in QEventDispatcherGlib::processEvents (this=0x7f25680aabc0, flags=...) at kernel/qeventdispatcher_glib.cpp:452
#5  0x00007f258c9bba2f in QEventLoop::processEvents (this=this@entry=0x7f25197f9d50, flags=...) at kernel/qeventloop.cpp:149
#6  0x00007f258c9bbd10 in QEventLoop::exec (this=this@entry=0x7f25197f9d50, flags=...) at kernel/qeventloop.cpp:204
#7  0x00007f25900c8f2b in Digikam::WorkerObjectRunnable::run (this=0x778cc00) at /portage_builddir/portage/media-gfx/digikam-4.2.0/work/digikam-4.2.0/core/libs/threads/threadmanager.cpp:196
#8  0x00007f258c8b3dbb in QThreadPoolThread::run (this=0x4e679d0) at concurrent/qthreadpool.cpp:107
#9  0x00007f258c8c02dc in QThreadPrivate::start (arg=0x4e679d0) at thread/qthread_unix.cpp:338
#10 0x00007f2589a172da in start_thread (arg=0x7f25197fa700) at pthread_create.c:309
#11 0x00007f258badc32d in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:111

Thread 1 (Thread 0x7f2592a77840 (LWP 24459)):
#0  pthread_cond_wait () at ../nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S:185
#1  0x00007f258c8c0873 in wait (time=18446744073709551615, this=0x229cc60) at thread/qwaitcondition_unix.cpp:86
#2  QWaitCondition::wait (this=this@entry=0x251ea00, mutex=0x251e9d8, time=time@entry=18446744073709551615) at thread/qwaitcondition_unix.cpp:158
#3  0x00007f258c8b35c7 in QThreadPoolPrivate::waitForDone (this=0x251e950, msecs=msecs@entry=-1) at concurrent/qthreadpool.cpp:298
#4  0x00007f258c8b5045 in QThreadPool::~QThreadPool (this=0x251ce30, __in_chrg=<optimized out>) at concurrent/qthreadpool.cpp:440
#5  0x00007f258c8b5089 in QThreadPool::~QThreadPool (this=0x251ce30, __in_chrg=<optimized out>) at concurrent/qthreadpool.cpp:442
#6  0x00007f258c9cf781 in QObjectPrivate::deleteChildren (this=this@entry=0x21776b0) at kernel/qobject.cpp:1907
#7  0x00007f258c9d63a6 in QObject::~QObject (this=0x24ebed0, __in_chrg=<optimized out>) at kernel/qobject.cpp:926
#8  0x00007f25900c8827 in ~ThreadManagerCreator (this=0x24ebed0, __in_chrg=<optimized out>) at /portage_builddir/portage/media-gfx/digikam-4.2.0/work/digikam-4.2.0/core/libs/threads/threadmanager.cpp:236
#9  destroy () at /portage_builddir/portage/media-gfx/digikam-4.2.0/work/digikam-4.2.0/core/libs/threads/threadmanager.cpp:241
#10 0x00007f258ba29771 in __run_exit_handlers (status=1, listp=0x7f258bd945c8 <__exit_funcs>, run_list_atexit=run_list_atexit@entry=true) at exit.c:82
#11 0x00007f258ba297f5 in __GI_exit (status=<optimized out>) at exit.c:104
#12 0x00007f258d44fca8 in qt_xio_errhandler () at kernel/qapplication_x11.cpp:772
#13 0x00007f258e113ba0 in KApplication::xioErrhandler (this=0x7fff2e5487d0, dpy=0x208d090) at /portage_builddir/portage/kde-base/kdelibs-4.12.5-r2/work/kdelibs-4.12.5/kdeui/kernel/kapplication.cpp:419
#14 0x00007f2589fb414e in _XIOError (dpy=0x208d090) at /tmp/portage/x11-libs/libX11-1.6.2/work/libX11-1.6.2/src/XlibInt.c:1498
#15 0x00007f2589fb1b9d in _XEventsQueued (dpy=0x208d090, mode=<optimized out>) at /tmp/portage/x11-libs/libX11-1.6.2/work/libX11-1.6.2/src/xcb_io.c:366
#16 0x00007f2589fa338f in XEventsQueued (dpy=0x208d090, mode=2) at /tmp/portage/x11-libs/libX11-1.6.2/work/libX11-1.6.2/src/Pending.c:43
#17 0x00007f258d485ffc in x11EventSourceCheck (s=0x2086820) at kernel/qguieventdispatcher_glib.cpp:85
#18 0x00007f2584c3b998 in g_main_context_check (context=context@entry=0x2088590, max_priority=0, fds=fds@entry=0x62d9290, n_fds=n_fds@entry=10) at /portage_builddir/portage/dev-libs/glib-2.40.0-r1/work/glib-2.40.0/glib/gmain.c:3575
#19 0x00007f2584c3beb5 in g_main_context_iterate (context=context@entry=0x2088590, block=block@entry=1, dispatch=dispatch@entry=1, self=<optimized out>) at /portage_builddir/portage/dev-libs/glib-2.40.0-r1/work/glib-2.40.0/glib/gmain.c:3731
#20 0x00007f2584c3c04c in g_main_context_iteration (context=0x2088590, may_block=1) at /portage_builddir/portage/dev-libs/glib-2.40.0-r1/work/glib-2.40.0/glib/gmain.c:3795
#21 0x00007f258c9eb8bc in QEventDispatcherGlib::processEvents (this=0x1ffad90, flags=...) at kernel/qeventdispatcher_glib.cpp:450
#22 0x00007f258d486586 in QGuiEventDispatcherGlib::processEvents (this=<optimized out>, flags=...) at kernel/qguieventdispatcher_glib.cpp:204
#23 0x00007f258c9bba2f in QEventLoop::processEvents (this=this@entry=0x7fff2e5481c0, flags=...) at kernel/qeventloop.cpp:149
#24 0x00007f258c9bbd10 in QEventLoop::exec (this=this@entry=0x7fff2e5481c0, flags=...) at kernel/qeventloop.cpp:204
#25 0x00007f258c9c0fc8 in QCoreApplication::exec () at kernel/qcoreapplication.cpp:1221
#26 0x00007f258d3e363c in QApplication::exec () at kernel/qapplication.cpp:3823
#27 0x000000000049d7b8 in main (argc=5, argv=0x7fff2e548a08) at /portage_builddir/portage/media-gfx/digikam-4.2.0/work/digikam-4.2.0/core/digikam/main/main.cpp:236

The reporter indicates this bug may be a duplicate of or related to bug 330282.

Possible duplicates by query: bug 336275, bug 334929, bug 333095, bug 332381, bug 330282.

Reported using DrKonqi
Comment 1 caulier.gilles 2014-08-10 18:56:22 UTC
The backtrace report a C++ exception but not code appears in details.

Please run digiKam into GDB like explained in this page and try again :

https://www.digikam.org/contrib

Gilles Caulier
Comment 2 Christian 2014-08-11 13:39:28 UTC
Dear Gilles! Thanks! I've followed your instructions from that website. Here's the first backtrace (gdb). I'll do the other ones next (valgrind and kdebugdialog tool).


ca@puolukka ~ $ gdb digikam
GNU gdb (Gentoo 7.6.2 p1) 7.6.2
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-pc-linux-gnu".
For bug reporting instructions, please see:
<http://bugs.gentoo.org/>...
Reading symbols from /usr/bin/digikam...Reading symbols from /usr/lib64/debug/usr/bin/digikam.debug...done.
done.
(gdb) catch throw
Function "__cxa_throw" not defined.
Catchpoint 1 (throw)
(gdb) run
Starting program: /usr/bin/digikam 
warning: Could not load shared library symbols for linux-vdso.so.1.
Do you need "set solib-search-path" or "set sysroot"?
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib64/libthread_db.so.1".
[New Thread 0x7fffd4e8a700 (LWP 17758)]
[New Thread 0x7fffcffff700 (LWP 17759)]
Object::connect: No such signal org::freedesktop::UPower::DeviceAdded(QString)
Object::connect: No such signal org::freedesktop::UPower::DeviceRemoved(QString)
[New Thread 0x7fffcf7fe700 (LWP 17760)]
QSqlDatabasePrivate::removeDatabase: connection 'ConnectionTest' is still in use, all queries will cease to work.
[Thread 0x7fffcf7fe700 (LWP 17760) exited]
[New Thread 0x7fffcf7fe700 (LWP 17764)]
[New Thread 0x7fffcc81a700 (LWP 17780)]
[Thread 0x7fffcc81a700 (LWP 17780) exited]
[New Thread 0x7fffcc81a700 (LWP 17781)]
[New Thread 0x7fffb6efd700 (LWP 17783)]
[Thread 0x7fffcc81a700 (LWP 17781) exited]
[Thread 0x7fffb6efd700 (LWP 17783) exited]
[New Thread 0x7fffb6efd700 (LWP 17785)]
[New Thread 0x7fffcc81a700 (LWP 17786)]
[New Thread 0x7fffbba22700 (LWP 17787)]
[New Thread 0x7fffbb221700 (LWP 17788)]
[New Thread 0x7fffbaa20700 (LWP 17789)]
[New Thread 0x7fffba21f700 (LWP 17790)]                                                                                         
[New Thread 0x7fffb9a1e700 (LWP 17791)]                                                                                         
[New Thread 0x7fffb921d700 (LWP 17792)]                                                                                         
[New Thread 0x7fffb8a1c700 (LWP 17793)]                                                                                         
[New Thread 0x7fffb5e34700 (LWP 17794)]                                                                                         
[New Thread 0x7fffb5633700 (LWP 17795)]                                                                                         
[New Thread 0x7fffb4e32700 (LWP 17796)]                                                                                         
[New Thread 0x7fff8ffff700 (LWP 17797)]                                                                                         
[New Thread 0x7fff8f7fe700 (LWP 17798)]                                                                                         
[New Thread 0x7fff8effd700 (LWP 17799)]                                                                                         
[New Thread 0x7fff8e7fc700 (LWP 17800)]                                                                                         
[New Thread 0x7fff8dffb700 (LWP 17801)]                                                                                         
[New Thread 0x7fff8d7fa700 (LWP 17802)]                                                                                         
[New Thread 0x7fff8cff9700 (LWP 17803)]                                                                                         
[New Thread 0x7fff83fff700 (LWP 17804)]                                                                                         
[New Thread 0x7fff837fe700 (LWP 17805)]                                                                                         
[New Thread 0x7fff82ffd700 (LWP 17806)]                                                                                         
[New Thread 0x7fff827fc700 (LWP 17807)]                                                                                         
[New Thread 0x7fff81ffb700 (LWP 17808)]                                                                                         
[New Thread 0x7fff817fa700 (LWP 17809)]                                                                                         
[New Thread 0x7fff80ff9700 (LWP 17810)]                                                                                         
[New Thread 0x7fff807f8700 (LWP 17811)]                                                                                         
[New Thread 0x7fff7fff7700 (LWP 17812)]                                                                                         
[New Thread 0x7fff7f7f6700 (LWP 17813)]                                                                                         
[New Thread 0x7fff7eff5700 (LWP 17814)]                                                                                         
[New Thread 0x7fff7e7f4700 (LWP 17815)]                                                                                         
[New Thread 0x7fff7dff3700 (LWP 17816)]                                                                                         
[New Thread 0x7fff7d7f2700 (LWP 17817)]                                                                                         
[New Thread 0x7fff7cff1700 (LWP 17818)]                                                                                         
[New Thread 0x7fff7c7f0700 (LWP 17819)]
[New Thread 0x7fff7bfef700 (LWP 17820)]
[Thread 0x7fff7c7f0700 (LWP 17819) exited]
[Thread 0x7fff7bfef700 (LWP 17820) exited]
[Thread 0x7fffba21f700 (LWP 17790) exited]
[Thread 0x7fffb9a1e700 (LWP 17791) exited]
[Thread 0x7fff7cff1700 (LWP 17818) exited]
[Thread 0x7fff7d7f2700 (LWP 17817) exited]
[Thread 0x7fff7dff3700 (LWP 17816) exited]
[Thread 0x7fff7eff5700 (LWP 17814) exited]
[Thread 0x7fff7f7f6700 (LWP 17813) exited]
[Thread 0x7fff7fff7700 (LWP 17812) exited]
[Thread 0x7fff807f8700 (LWP 17811) exited]
[Thread 0x7fff80ff9700 (LWP 17810) exited]
[Thread 0x7fff817fa700 (LWP 17809) exited]
[Thread 0x7fff81ffb700 (LWP 17808) exited]
[Thread 0x7fff827fc700 (LWP 17807) exited]
[Thread 0x7fff82ffd700 (LWP 17806) exited]
[Thread 0x7fff7e7f4700 (LWP 17815) exited]
[Thread 0x7fff837fe700 (LWP 17805) exited]
[Thread 0x7fff8cff9700 (LWP 17803) exited]
[Thread 0x7fff8d7fa700 (LWP 17802) exited]
[Thread 0x7fff8e7fc700 (LWP 17800) exited]
[Thread 0x7fff8effd700 (LWP 17799) exited]
[Thread 0x7fff8f7fe700 (LWP 17798) exited]
[Thread 0x7fffb8a1c700 (LWP 17793) exited]
[Thread 0x7fffbaa20700 (LWP 17789) exited]
[Thread 0x7fffbb221700 (LWP 17788) exited]
[Thread 0x7fffbba22700 (LWP 17787) exited]
[Thread 0x7fffb6efd700 (LWP 17785) exited]
[Thread 0x7fff83fff700 (LWP 17804) exited]
[Thread 0x7fffb4e32700 (LWP 17796) exited]
[Thread 0x7fff8dffb700 (LWP 17801) exited]
[Thread 0x7fff8ffff700 (LWP 17797) exited]
[Thread 0x7fffb5e34700 (LWP 17794) exited]
[Thread 0x7fffcc81a700 (LWP 17786) exited]
[New Thread 0x7fffcc81a700 (LWP 18362)]
[New Thread 0x7fffb5e34700 (LWP 18378)]
[Thread 0x7fffcc81a700 (LWP 18362) exited]
[Thread 0x7fffb5e34700 (LWP 18378) exited]
[Thread 0x7fffb5633700 (LWP 17795) exited]
[Thread 0x7fffb921d700 (LWP 17792) exited]
[Thread 0x7fffcf7fe700 (LWP 17764) exited]
[Thread 0x7fffcffff700 (LWP 17759) exited]
[Thread 0x7fffd4e8a700 (LWP 17758) exited]

Program terminated with signal SIGKILL, Killed.
The program no longer exists.
(gdb) bt
No stack.
(gdb) quit
ca@puolukka ~ $
Comment 3 Christian 2014-08-11 18:10:33 UTC
Dear Gilles - here's the output from Valgrind. The top is cut off because it didn't all fit into the console window. Additionally, I did run the kde-debugdialog thing as instructed on the webpage, but there was no output from the program or I don't know where to find the kdedbug.dbg file that would be created - it was nowhere in my home directory tree and not in /usr tree either.

Valgrind output: (The reason why it stopped working is, it ran out of swap space).

[The top is cut off because the console window was full. I'm deleting a few more "meaningless lines" because this window doesn't let me post more than 65535 characters.]
--23075:0:aspacem  934: file 002e2bc000-002e2bcfff    4096 rw--- d=0xfd03 i=398988  o=122880  (268)
--23075:0:aspacem  935: file 002e2bd000-002ecccfff     10m rw--- d=0xfd0d i=9308577 o=0       (190)
--23075:0:aspacem  936: file 002eccd000-002eef7fff 2273280 r---- d=0xfd0d i=9306585 o=0       (269)
--23075:0:aspacem  937: anon 002eef8000-002faf7fff     12m rwx-H
--23075:0:aspacem  938: file 002faf8000-002fb50fff  364544 r---- d=0xfd03 i=1449537 o=0       (270)
--23075:0:aspacem  939: anon 002fb51000-002ff50fff 4194304 rwx-H
--23075:0:aspacem  940: file 002ff51000-002ff60fff   65536 r-xT- d=0xfd03 i=155192  o=0       (271)
--23075:0:aspacem  941: file 002ff61000-0030160fff 2097152 ----- d=0xfd03 i=155192  o=65536   (271)
--23075:0:aspacem  942: file 0030161000-0030161fff    4096 r---- d=0xfd03 i=155192  o=65536   (271)
--23075:0:aspacem  943: file 0030162000-0030162fff    4096 rw--- d=0xfd03 i=155192  o=69632   (271)
--23075:0:aspacem  944: file 0030163000-0030244fff  925696 r-xT- d=0xfd03 i=18257   o=0       (272)
--23075:0:aspacem  945: file 0030245000-0030444fff 2097152 ----- d=0xfd03 i=18257   o=925696  (272)
--23075:0:aspacem  946: file 0030445000-003044afff   24576 r---- d=0xfd03 i=18257   o=925696  (272)
--23075:0:aspacem  947: file 003044b000-003044cfff    8192 rw--- d=0xfd03 i=18257   o=950272  (272)
--23075:0:aspacem  948: file 003044d000-003044dfff    4096 r---- d=0xfd03 i=4484804 o=0       (273)
--23075:0:aspacem  949: file 003044e000-003044efff    4096 r---- d=0xfd03 i=4490934 o=0       (274)
--23075:0:aspacem  950: file 003044f000-003044ffff    4096 r---- d=0xfd03 i=4479084 o=0       (275)
--23075:0:aspacem  951: file 0030450000-0030450fff    4096 r---- d=0xfd03 i=4485742 o=0       (276)
--23075:0:aspacem  952: file 0030451000-0030451fff    4096 r---- d=0xfd03 i=4481174 o=0       (277)
--23075:0:aspacem  953: file 0030452000-0030452fff    4096 r---- d=0xfd03 i=4482980 o=0       (278)
--23075:0:aspacem  954: file 0030453000-00304a3fff  331776 r-xT- d=0xfd03 i=135960  o=0       (279)
--23075:0:aspacem  955: file 00304a4000-00306a3fff 2097152 ----- d=0xfd03 i=135960  o=331776  (279)
--23075:0:aspacem  956: file 00306a4000-00306a6fff   12288 r---- d=0xfd03 i=135960  o=331776  (279)
--23075:0:aspacem  957: file 00306a7000-00306a7fff    4096 rw--- d=0xfd03 i=135960  o=344064  (279)
--23075:0:aspacem  958: anon 00306a8000-00306a8fff    4096 rw---
--23075:0:aspacem  959: anon 00306a9000-00312a8fff     12m rwx-H
--23075:0:aspacem  960:      00312a9000-0031393fff  962560
--23075:0:aspacem  961: anon 0031394000-0032735fff     19m rwx-H
--23075:0:aspacem  962: file 0032736000-0032741fff   49152 r-xT- d=0xfd03 i=16455   o=0       (479)
--23075:0:aspacem  963: file 0032742000-0032941fff 2097152 ----- d=0xfd03 i=16455   o=49152   (479)
--23075:0:aspacem  964: file 0032942000-0032942fff    4096 r---- d=0xfd03 i=16455   o=49152   (479)
--23075:0:aspacem  965: file 0032943000-0032943fff    4096 rw--- d=0xfd03 i=16455   o=53248   (479)
--23075:0:aspacem  966: anon 0032944000-0032b5dfff 2203648 rw---
--23075:0:aspacem  967: anon 0032b5e000-003435dfff     24m rwx-H
--23075:0:aspacem  968:      003435e000-00346a9fff 3457024
--23075:0:aspacem  969: file 00346aa000-00346adfff   16384 r---- d=0xfd03 i=4485607 o=0       (281)
--23075:0:aspacem  970: file 00346ae000-00346c3fff   90112 r---- d=0xfd03 i=4483693 o=0       (282)
--23075:0:aspacem  971: file 00346c4000-00346e4fff  135168 r-xT- d=0xfd03 i=151049  o=0       (283)
--23075:0:aspacem  972: file 00346e5000-00348e3fff 2093056 ----- d=0xfd03 i=151049  o=135168  (283)
--23075:0:aspacem  973: file 00348e4000-00348e4fff    4096 r---- d=0xfd03 i=151049  o=131072  (283)
--23075:0:aspacem  974: file 00348e5000-00348e5fff    4096 rw--- d=0xfd03 i=151049  o=135168  (283)
--23075:0:aspacem  975: file 00348e6000-00348f5fff   65536 r-x-- d=0xfd06 i=46      o=0       (286)
--23075:0:aspacem  976: file 00348f6000-0034905fff   65536 rw--- d=0xfd06 i=46      o=0       (286)
--23075:0:aspacem  977: file 0034906000-0034906fff    4096 r---- d=0xfd03 i=4484766 o=0       (287)
--23075:0:aspacem  978: file 0034907000-0034907fff    4096 r---- d=0xfd03 i=4490896 o=0       (299)
--23075:0:aspacem  979: file 0034908000-0034908fff    4096 r---- d=0xfd03 i=4479046 o=0       (300)
--23075:0:aspacem  980: file 0034909000-0034909fff    4096 r---- d=0xfd03 i=4485704 o=0       (301)
--23075:0:aspacem  981: file 003490a000-003490afff    4096 r---- d=0xfd03 i=4481136 o=0       (302)
--23075:0:aspacem  982: file 003490b000-003490bfff    4096 r---- d=0xfd03 i=4482938 o=0       (303)
--23075:0:aspacem  983: file 003490c000-003490cfff    4096 r---- d=0xfd03 i=4457131 o=0       (310)
--23075:0:aspacem  984: file 003490d000-003490ffff   12288 r---- d=0xfd03 i=4457212 o=0       (311)
--23075:0:aspacem  985: file 0034910000-0034912fff   12288 r---- d=0xfd03 i=4457023 o=0       (312)
--23075:0:aspacem  986: file 0034913000-0034915fff   12288 r---- d=0xfd03 i=4456969 o=0       (313)
--23075:0:aspacem  987: file 0034916000-0034918fff   12288 r---- d=0xfd03 i=4457320 o=0       (314)
--23075:0:aspacem  988: file 0034919000-003491bfff   12288 r---- d=0xfd03 i=4456996 o=0       (315)
--23075:0:aspacem  989: file 003491c000-003491dfff    8192 r---- d=0xfd03 i=4457154 o=0       (317)
--23075:0:aspacem  990: file 003491e000-003491ffff    8192 r---- d=0xfd03 i=4457235 o=0       (318)
--23075:0:aspacem  991: file 0034920000-0034920fff    4096 r---- d=0xfd03 i=4457150 o=0       (324)
--23075:0:aspacem  992: file 0034921000-0034957fff  225280 r-xT- d=0xfd03 i=42992   o=0       (285)
--23075:0:aspacem  993: file 0034958000-0034b57fff 2097152 ----- d=0xfd03 i=42992   o=225280  (285)
--23075:0:aspacem  994: file 0034b58000-0034b58fff    4096 r---- d=0xfd03 i=42992   o=225280  (285)
--23075:0:aspacem  995: file 0034b59000-0034b5afff    8192 rw--- d=0xfd03 i=42992   o=229376  (285)
--23075:0:aspacem  996: file 0034b5b000-0034b7afff  131072 r-xT- d=0xfd03 i=145599  o=0       (434)
--23075:0:aspacem  997: file 0034b7b000-0034d7afff 2097152 ----- d=0xfd03 i=145599  o=131072  (434)
--23075:0:aspacem  998: file 0034d7b000-0034d7bfff    4096 r---- d=0xfd03 i=145599  o=131072  (434)
--23075:0:aspacem  999: file 0034d7c000-0034d7cfff    4096 rw--- d=0xfd03 i=145599  o=135168  (434)
--23075:0:aspacem  1000: file 0034d7d000-0034d7dfff    4096 r---- d=0xfd03 i=4462908 o=0       (435)
--23075:0:aspacem  1001: file 0034d7e000-0034d7efff    4096 r---- d=0xfd03 i=4462927 o=0       (436)
--23075:0:aspacem  1002: file 0034d7f000-0034d7ffff    4096 r---- d=0xfd03 i=4462889 o=0       (437)
--23075:0:aspacem  1003: file 0034d80000-0034d81fff    8192 r---- d=0xfd03 i=4462851 o=0       (438)
--23075:0:aspacem  1004: file 0034d82000-0034d82fff    4096 r---- d=0xfd03 i=4462947 o=0       (439)
--23075:0:aspacem  1005: file 0034d83000-0034d83fff    4096 r---- d=0xfd03 i=4462870 o=0       (440)
--23075:0:aspacem  1006: file 0034d84000-0034db1fff  188416 r-xT- d=0xfd03 i=145522  o=0       (441)
--23075:0:aspacem  1007: file 0034db2000-0034fb0fff 2093056 ----- d=0xfd03 i=145522  o=188416  (441)
--23075:0:aspacem  1008: file 0034fb1000-0034fb1fff    4096 r---- d=0xfd03 i=145522  o=184320  (441)
--23075:0:aspacem  1009: file 0034fb2000-0034fb2fff    4096 rw--- d=0xfd03 i=145522  o=188416  (441)
--23075:0:aspacem  1010: file 0034fb3000-0034fb3fff    4096 r---- d=0xfd03 i=4462922 o=0       (442)
--23075:0:aspacem  1011: file 0034fb4000-0034fb4fff    4096 r---- d=0xfd03 i=4462941 o=0       (443)
--23075:0:aspacem  1012: file 0034fb5000-0034fb6fff    8192 r---- d=0xfd03 i=4462903 o=0       (444)
--23075:0:aspacem  1013: file 0034fb7000-0034fb8fff    8192 r---- d=0xfd03 i=4462865 o=0       (445)
--23075:0:aspacem  1014: file 0034fb9000-0034fbafff    8192 r---- d=0xfd03 i=4462962 o=0       (446)
--23075:0:aspacem  1015: file 0034fbb000-0034fbbfff    4096 r---- d=0xfd03 i=4462884 o=0       (447)
--23075:0:aspacem  1016: file 0034fbc000-0034fcbfff   65536 r-xT- d=0xfd03 i=145526  o=0       (448)
--23075:0:aspacem  1017: file 0034fcc000-00351cafff 2093056 ----- d=0xfd03 i=145526  o=65536   (448)
--23075:0:aspacem  1018: file 00351cb000-00351cbfff    4096 r---- d=0xfd03 i=145526  o=61440   (448)
--23075:0:aspacem  1019: file 00351cc000-00351ccfff    4096 rw--- d=0xfd03 i=145526  o=65536   (448)
--23075:0:aspacem  1020: file 00351cd000-00351cffff   12288 r---- d=0xfd03 i=4462913 o=0       (449)
--23075:0:aspacem  1021: file 00351d0000-00351d2fff   12288 r---- d=0xfd03 i=4462932 o=0       (450)
--23075:0:aspacem  1022: file 00351d3000-00351d5fff   12288 r---- d=0xfd03 i=4462894 o=0       (451)
--23075:0:aspacem  1023: file 00351d6000-00351d8fff   12288 r---- d=0xfd03 i=4462856 o=0       (452)
--23075:0:aspacem  1024: file 00351d9000-00351dbfff   12288 r---- d=0xfd03 i=4462953 o=0       (453)
--23075:0:aspacem  1025: file 00351dc000-00351ddfff    8192 r---- d=0xfd03 i=4462875 o=0       (454)
--23075:0:aspacem  1026:      00351de000-00351dffff    8192
--23075:0:aspacem  1027: anon 00351e0000-00351effff   65536 rw---
--23075:0:aspacem  1028:      00351f0000-003535bfff 1490944
--23075:0:aspacem  1029: anon 003535c000-003575bfff 4194304 rwx-H
--23075:0:aspacem  1030: file 003575c000-0035772fff   94208 r-xT- d=0xfd03 i=150284  o=0       (284)
--23075:0:aspacem  1031: file 0035773000-0035972fff 2097152 ----- d=0xfd03 i=150284  o=94208   (284)
--23075:0:aspacem  1032: file 0035973000-0035973fff    4096 r---- d=0xfd03 i=150284  o=94208   (284)
--23075:0:aspacem  1033: file 0035974000-0035974fff    4096 rw--- d=0xfd03 i=150284  o=98304   (284)
--23075:0:aspacem  1034: anon 0035975000-0035d74fff 4194304 rwx-H
--23075:0:aspacem  1035: file 0035d75000-0035d7cfff   32768 r-xT- d=0xfd03 i=150283  o=0       (288)
--23075:0:aspacem  1036: file 0035d7d000-0035f7cfff 2097152 ----- d=0xfd03 i=150283  o=32768   (288)
--23075:0:aspacem  1037: file 0035f7d000-0035f7dfff    4096 r---- d=0xfd03 i=150283  o=32768   (288)
--23075:0:aspacem  1038: file 0035f7e000-0035f7efff    4096 rw--- d=0xfd03 i=150283  o=36864   (288)
--23075:0:aspacem  1039: file 0035f7f000-0035f7ffff    4096 r---- d=0xfd03 i=4462917 o=0       (331)
--23075:0:aspacem  1040: anon 0035f80000-0035f9ffff  131072 rw---
--23075:0:aspacem  1041: file 0035fa0000-0035fa1fff    8192 r---- d=0xfd03 i=4457046 o=0       (319)
--23075:0:aspacem  1042: file 0035fa2000-0035fa4fff   12288 r---- d=0xfd03 i=4456992 o=0       (320)
--23075:0:aspacem  1043: file 0035fa5000-0035fa6fff    8192 r---- d=0xfd03 i=4457343 o=0       (321)
--23075:0:aspacem  1044: file 0035fa7000-0035fa8fff    8192 r---- d=0xfd03 i=4457019 o=0       (322)
--23075:0:aspacem  1045: file 0035fa9000-0035fabfff   12288 r---- d=0xfd03 i=4457231 o=0       (325)
--23075:0:aspacem  1046: file 0035fac000-0035faefff   12288 r---- d=0xfd03 i=4457042 o=0       (326)
--23075:0:aspacem  1047: file 0035faf000-0035fb1fff   12288 r---- d=0xfd03 i=4456988 o=0       (327)
--23075:0:aspacem  1048: file 0035fb2000-0035fb4fff   12288 r---- d=0xfd03 i=4457339 o=0       (328)
--23075:0:aspacem  1049: file 0035fb5000-0035fb7fff   12288 r---- d=0xfd03 i=4457015 o=0       (329)
--23075:0:aspacem  1050: file 0035fb8000-0035fb9fff    8192 r---- d=0xfd03 i=4462936 o=0       (332)
--23075:0:aspacem  1051: file 0035fba000-0035fe1fff  163840 r-xT- d=0xfd03 i=42606   o=0       (290)
--23075:0:aspacem  1052: file 0035fe2000-00361e1fff 2097152 ----- d=0xfd03 i=42606   o=163840  (290)
--23075:0:aspacem  1053: file 00361e2000-00361e2fff    4096 r---- d=0xfd03 i=42606   o=163840  (290)
--23075:0:aspacem  1054: file 00361e3000-00361e3fff    4096 rw--- d=0xfd03 i=42606   o=167936  (290)
--23075:0:aspacem  1055: anon 00361e4000-00365e3fff 4194304 rwx-H
--23075:0:aspacem  1056: file 00365e4000-0036627fff  278528 r-xT- d=0xfd03 i=146221  o=0       (289)
--23075:0:aspacem  1057: file 0036628000-0036826fff 2093056 ----- d=0xfd03 i=146221  o=278528  (289)
--23075:0:aspacem  1058: file 0036827000-0036827fff    4096 r---- d=0xfd03 i=146221  o=274432  (289)
--23075:0:aspacem  1059: file 0036828000-0036829fff    8192 rw--- d=0xfd03 i=146221  o=278528  (289)
--23075:0:aspacem  1060: file 003682a000-0036839fff   65536 r-xT- d=0xfd03 i=150286  o=0       (291)
--23075:0:aspacem  1061: file 003683a000-0036a38fff 2093056 ----- d=0xfd03 i=150286  o=65536   (291)
--23075:0:aspacem  1062: file 0036a39000-0036a39fff    4096 r---- d=0xfd03 i=150286  o=61440   (291)
--23075:0:aspacem  1063: file 0036a3a000-0036a3bfff    8192 rw--- d=0xfd03 i=150286  o=65536   (291)
--23075:0:aspacem  1064: file 0036a3c000-0036a42fff   28672 r-xT- d=0xfd03 i=42457   o=0       (293)
--23075:0:aspacem  1065: file 0036a43000-0036c41fff 2093056 ----- d=0xfd03 i=42457   o=28672   (293)
--23075:0:aspacem  1066: file 0036c42000-0036c42fff    4096 r---- d=0xfd03 i=42457   o=24576   (293)
--23075:0:aspacem  1067: file 0036c43000-0036c43fff    4096 rw--- d=0xfd03 i=42457   o=28672   (293)
--23075:0:aspacem  1068: file 0036c44000-0036c54fff   69632 r-xT- d=0xfd03 i=151033  o=0       (292)
--23075:0:aspacem  1069: file 0036c55000-0036e54fff 2097152 ----- d=0xfd03 i=151033  o=69632   (292)
--23075:0:aspacem  1070: file 0036e55000-0036e55fff    4096 r---- d=0xfd03 i=151033  o=69632   (292)
--23075:0:aspacem  1071: file 0036e56000-0036e56fff    4096 rw--- d=0xfd03 i=151033  o=73728   (292)
--23075:0:aspacem  1072: file 0036e57000-0036e5afff   16384 r-xT- d=0xfd03 i=101702  o=0       (295)
--23075:0:aspacem  1073: file 0036e5b000-0037059fff 2093056 ----- d=0xfd03 i=101702  o=16384   (295)
--23075:0:aspacem  1074: file 003705a000-003705afff    4096 r---- d=0xfd03 i=101702  o=12288   (295)
--23075:0:aspacem  1075: file 003705b000-003705bfff    4096 rw--- d=0xfd03 i=101702  o=16384   (295)
--23075:0:aspacem  1076: file 003705c000-0037065fff   40960 r-xT- d=0xfd03 i=145626  o=0       (455)
--23075:0:aspacem  1077: file 0037066000-0037264fff 2093056 ----- d=0xfd03 i=145626  o=40960   (455)
--23075:0:aspacem  1078: file 0037265000-0037265fff    4096 r---- d=0xfd03 i=145626  o=36864   (455)
--23075:0:aspacem  1079: file 0037266000-0037266fff    4096 rw--- d=0xfd03 i=145626  o=40960   (455)
--23075:0:aspacem  1080: file 0037267000-003729efff  229376 r-xT- d=0xfd03 i=145510  o=0       (456)
--23075:0:aspacem  1081: file 003729f000-003749efff 2097152 ----- d=0xfd03 i=145510  o=229376  (456)
--23075:0:aspacem  1082: file 003749f000-00374a0fff    8192 r---- d=0xfd03 i=145510  o=229376  (456)
--23075:0:aspacem  1083: file 00374a1000-00374a1fff    4096 rw--- d=0xfd03 i=145510  o=237568  (456)
--23075:0:aspacem  1084: file 00374a2000-00374bcfff  110592 r-xT- d=0xfd03 i=145514  o=0       (457)
--23075:0:aspacem  1085: file 00374bd000-00376bcfff 2097152 ----- d=0xfd03 i=145514  o=110592  (457)
--23075:0:aspacem  1086: file 00376bd000-00376bdfff    4096 r---- d=0xfd03 i=145514  o=110592  (457)
--23075:0:aspacem  1087: file 00376be000-00376befff    4096 rw--- d=0xfd03 i=145514  o=114688  (457)
--23075:0:aspacem  1088:      00376bf000-003785cfff 1695744
--23075:0:aspacem  1089: file 003785d000-00378affff  339968 r-xT- d=0xfd03 i=150280  o=0       (294)
--23075:0:aspacem  1090: file 00378b0000-0037aaefff 2093056 ----- d=0xfd03 i=150280  o=339968  (294)
--23075:0:aspacem  1091: file 0037aaf000-0037aaffff    4096 r---- d=0xfd03 i=150280  o=335872  (294)
--23075:0:aspacem  1092: file 0037ab0000-0037ab1fff    8192 rw--- d=0xfd03 i=150280  o=339968  (294)
--23075:0:aspacem  1093: anon 0037ab2000-0037ab2fff    4096 rw---
--23075:0:aspacem  1094: file 0037ab3000-0037acefff  114688 r-xT- d=0xfd03 i=150275  o=0       (296)
--23075:0:aspacem  1095: file 0037acf000-0037ccefff 2097152 ----- d=0xfd03 i=150275  o=114688  (296)
--23075:0:aspacem  1096: file 0037ccf000-0037ccffff    4096 r---- d=0xfd03 i=150275  o=114688  (296)
--23075:0:aspacem  1097: file 0037cd0000-0037cd0fff    4096 rw--- d=0xfd03 i=150275  o=118784  (296)
--23075:0:aspacem  1098: anon 0037cd1000-0037cd1fff    4096 rw---
--23075:0:aspacem  1099: file 0037cd2000-0037cdffff   57344 r-xT- d=0xfd03 i=150352  o=0       (297)
--23075:0:aspacem  1100: file 0037ce0000-0037edefff 2093056 ----- d=0xfd03 i=150352  o=57344   (297)
--23075:0:aspacem  1101: file 0037edf000-0037edffff    4096 r---- d=0xfd03 i=150352  o=53248   (297)
--23075:0:aspacem  1102: file 0037ee0000-0037ee0fff    4096 rw--- d=0xfd03 i=150352  o=57344   (297)
--23075:0:aspacem  1103: file 0037ee1000-0037ee2fff    8192 r---- d=0xfd03 i=4462898 o=0       (333)
--23075:0:aspacem  1104: file 0037ee3000-0037ee4fff    8192 r---- d=0xfd03 i=4462860 o=0       (334)
--23075:0:aspacem  1105: file 0037ee5000-0037ee6fff    8192 r---- d=0xfd03 i=4462957 o=0       (335)
--23075:0:aspacem  1106: file 0037ee7000-0037ee7fff    4096 r---- d=0xfd03 i=4462879 o=0       (336)
--23075:0:aspacem  1107: file 0037ee8000-0037ee8fff    4096 r---- d=0xfd03 i=4462918 o=0       (338)
--23075:0:aspacem  1108: file 0037ee9000-0037eeafff    8192 r---- d=0xfd03 i=4462937 o=0       (339)
--23075:0:aspacem  1109: file 0037eeb000-0037eedfff   12288 r---- d=0xfd03 i=4462899 o=0       (340)
--23075:0:aspacem  1110: file 0037eee000-0037ef0fff   12288 r---- d=0xfd03 i=4462861 o=0       (341)
--23075:0:aspacem  1111: file 0037ef1000-0037ef3fff   12288 r---- d=0xfd03 i=4462958 o=0       (342)
--23075:0:aspacem  1112: file 0037ef4000-0037ef5fff    8192 r---- d=0xfd03 i=4462880 o=0       (343)
--23075:0:aspacem  1113: file 0037ef6000-0037ef6fff    4096 r---- d=0xfd03 i=4462916 o=0       (345)
--23075:0:aspacem  1114: file 0037ef7000-0037ef7fff    4096 r---- d=0xfd03 i=4462935 o=0       (346)
--23075:0:aspacem  1115: file 0037ef8000-0037ef8fff    4096 r---- d=0xfd03 i=4462897 o=0       (347)
--23075:0:aspacem  1116: file 0037ef9000-0037ef9fff    4096 r---- d=0xfd03 i=4462859 o=0       (348)
--23075:0:aspacem  1117: file 0037efa000-0037efafff    4096 r---- d=0xfd03 i=4462956 o=0       (349)
--23075:0:aspacem  1118: file 0037efb000-0037efbfff    4096 r---- d=0xfd03 i=4462878 o=0       (350)
--23075:0:aspacem  1119: file 0037efc000-0037efcfff    4096 r---- d=0xfd03 i=4457133 o=0       (352)
--23075:0:aspacem  1120: file 0037efd000-0037f00fff   16384 r---- d=0xfd03 i=4457214 o=0       (354)
--23075:0:aspacem  1121: file 0037f01000-0037f04fff   16384 r---- d=0xfd03 i=4457025 o=0       (355)
--23075:0:aspacem  1122: file 0037f05000-0037f08fff   16384 r---- d=0xfd03 i=4456971 o=0       (356)
--23075:0:aspacem  1123: file 0037f09000-0037f0cfff   16384 r---- d=0xfd03 i=4457322 o=0       (357)
--23075:0:aspacem  1124: file 0037f0d000-0037f0dfff    4096 r---- d=0xfd03 i=4456998 o=0       (358)
--23075:0:aspacem  1125: file 0037f0e000-0037f0efff    4096 r---- d=0xfd03 i=4462914 o=0       (360)
--23075:0:aspacem  1126: file 0037f0f000-0037f10fff    8192 r---- d=0xfd03 i=4462933 o=0       (361)
--23075:0:aspacem  1127: file 0037f11000-0037f12fff    8192 r---- d=0xfd03 i=4462895 o=0       (362)
--23075:0:aspacem  1128: file 0037f13000-0037f14fff    8192 r---- d=0xfd03 i=4462857 o=0       (363)
--23075:0:aspacem  1129: file 0037f15000-0037f16fff    8192 r---- d=0xfd03 i=4462954 o=0       (364)
--23075:0:aspacem  1130: file 0037f17000-0037f18fff    8192 r---- d=0xfd03 i=4462876 o=0       (365)
--23075:0:aspacem  1131: file 0037f19000-0037f19fff    4096 r---- d=0xfd03 i=4462912 o=0       (367)
--23075:0:aspacem  1132: file 0037f1a000-0037f1dfff   16384 r---- d=0xfd03 i=4462931 o=0       (369)
--23075:0:aspacem  1133: file 0037f1e000-0037f21fff   16384 r---- d=0xfd03 i=4462893 o=0       (370)
--23075:0:aspacem  1134: file 0037f22000-0037f25fff   16384 r---- d=0xfd03 i=4462855 o=0       (371)
--23075:0:aspacem  1135: file 0037f26000-0037f29fff   16384 r---- d=0xfd03 i=4462952 o=0       (372)
--23075:0:aspacem  1136: file 0037f2a000-0037f2bfff    8192 r---- d=0xfd03 i=4462874 o=0       (373)
--23075:0:aspacem  1137: file 0037f2c000-0037f2dfff    8192 r---- d=0xfd03 i=4462919 o=0       (376)
--23075:0:aspacem  1138: file 0037f2e000-0037f30fff   12288 r---- d=0xfd03 i=4462938 o=0       (377)
--23075:0:aspacem  1139: file 0037f31000-0037f33fff   12288 r---- d=0xfd03 i=4462900 o=0       (378)
--23075:0:aspacem  1140: file 0037f34000-0037f36fff   12288 r---- d=0xfd03 i=4462862 o=0       (379)
--23075:0:aspacem  1141: file 0037f37000-0037f39fff   12288 r---- d=0xfd03 i=4462959 o=0       (380)
--23075:0:aspacem  1142: file 0037f3a000-0037f3cfff   12288 r---- d=0xfd03 i=4462881 o=0       (381)
--23075:0:aspacem  1143: file 0037f3d000-0037f3dfff    4096 r---- d=0xfd03 i=4462921 o=0       (383)
--23075:0:aspacem  1144: file 0037f3e000-0037f48fff   45056 r---- d=0xfd03 i=4462940 o=0       (384)
--23075:0:aspacem  1145: file 0037f49000-0037f54fff   49152 r---- d=0xfd03 i=4462902 o=0       (385)
--23075:0:aspacem  1146: file 0037f55000-0037f60fff   49152 r---- d=0xfd03 i=4462864 o=0       (386)
--23075:0:aspacem  1147: file 0037f61000-0037f6cfff   49152 r---- d=0xfd03 i=4462961 o=0       (387)
--23075:0:aspacem  1148: file 0037f6d000-0037f77fff   45056 r---- d=0xfd03 i=4462883 o=0       (388)
--23075:0:aspacem  1149: file 0037f78000-0037f79fff    8192 r---- d=0xfd03 i=4462906 o=0       (391)
--23075:0:aspacem  1150: file 0037f7a000-0037f7efff   20480 r---- d=0xfd03 i=4462925 o=0       (392)
--23075:0:aspacem  1151: file 0037f7f000-0037f83fff   20480 r---- d=0xfd03 i=4462887 o=0       (393)
--23075:0:aspacem  1152: file 0037f84000-0037f88fff   20480 r---- d=0xfd03 i=4462849 o=0       (394)
--23075:0:aspacem  1153: file 0037f89000-0037f8dfff   20480 r---- d=0xfd03 i=4462944 o=0       (395)
--23075:0:aspacem  1154: file 0037f8e000-0037f91fff   16384 r---- d=0xfd03 i=4462868 o=0       (396)
--23075:0:aspacem  1155: file 0037f92000-0037f92fff    4096 r---- d=0xfd03 i=4462915 o=0       (398)
--23075:0:aspacem  1156: file 0037f93000-0037f95fff   12288 r---- d=0xfd03 i=4462934 o=0       (399)
--23075:0:aspacem  1157: file 0037f96000-0037f98fff   12288 r---- d=0xfd03 i=4462896 o=0       (400)
--23075:0:aspacem  1158: file 0037f99000-0037f9bfff   12288 r---- d=0xfd03 i=4462858 o=0       (401)
--23075:0:aspacem  1159: file 0037f9c000-0037f9efff   12288 r---- d=0xfd03 i=4462955 o=0       (402)
--23075:0:aspacem  1160: file 0037f9f000-0037fa1fff   12288 r---- d=0xfd03 i=4462877 o=0       (403)
--23075:0:aspacem  1161: file 0037fa2000-0037fa2fff    4096 r---- d=0xfd03 i=4462911 o=0       (405)
--23075:0:aspacem  1162: file 0037fa3000-0037fa4fff    8192 r---- d=0xfd03 i=4462930 o=0       (406)
--23075:0:aspacem  1163: file 0037fa5000-0037fa6fff    8192 r---- d=0xfd03 i=4462892 o=0       (407)
--23075:0:aspacem  1164: file 0037fa7000-0037fa8fff    8192 r---- d=0xfd03 i=4462854 o=0       (408)
--23075:0:aspacem  1165: file 0037fa9000-0037faafff    8192 r---- d=0xfd03 i=4462951 o=0       (409)
--23075:0:aspacem  1166: file 0037fab000-0037fabfff    4096 r---- d=0xfd03 i=4462873 o=0       (410)
--23075:0:aspacem  1167: file 0037fac000-0037fadfff    8192 r---- d=0xfd03 i=4457135 o=0       (419)
--23075:0:aspacem  1168: file 0037fae000-0037faffff    8192 r---- d=0xfd03 i=4457216 o=0       (420)
--23075:0:aspacem  1169: file 0037fb0000-0037fb1fff    8192 r---- d=0xfd03 i=4457027 o=0       (421)
--23075:0:aspacem  1170: file 0037fb2000-0037fb3fff    8192 r---- d=0xfd03 i=4456973 o=0       (422)
--23075:0:aspacem  1171: file 0037fb4000-0037fb5fff    8192 r---- d=0xfd03 i=4457324 o=0       (423)
--23075:0:aspacem  1172: file 0037fb6000-0037fb7fff    8192 r---- d=0xfd03 i=4457000 o=0       (424)
--23075:0:aspacem  1173: file 0037fb8000-0037fb8fff    4096 r---- d=0xfd03 i=4457139 o=0       (428)
--23075:0:aspacem  1174: file 0037fb9000-0037fc6fff   57344 r---- d=0xfd03 i=4457220 o=0       (429)
--23075:0:aspacem  1175: file 0037fc7000-0037fd4fff   57344 r---- d=0xfd03 i=4457031 o=0       (430)
--23075:0:aspacem  1176: file 0037fd5000-0037fe3fff   61440 r---- d=0xfd03 i=4456977 o=0       (431)
--23075:0:aspacem  1177: file 0037fe4000-0037ff1fff   57344 r---- d=0xfd03 i=4457328 o=0       (432)
--23075:0:aspacem  1178: file 0037ff2000-0037ffefff   53248 r---- d=0xfd03 i=4457004 o=0       (433)
--23075:0:aspacem  1179:      0037fff000-0037ffffff    4096
--23075:0:aspacem  1180: FILE 0038000000-0038064fff  413696 r-x-- d=0xfd03 i=1451013 o=0       (0)
--23075:0:aspacem  1181: file 0038065000-0038065fff    4096 r-xT- d=0xfd03 i=1451013 o=413696  (0)
--23075:0:aspacem  1182: FILE 0038066000-003836bfff 3170304 r-x-- d=0xfd03 i=1451013 o=417792  (0)
--23075:0:aspacem  1183:      003836c000-003856bfff 2097152
--23075:0:aspacem  1184: FILE 003856c000-003856efff   12288 rw--- d=0xfd03 i=1451013 o=3588096 (0)
--23075:0:aspacem  1185: ANON 003856f000-0039fdcfff     26m rw---
--23075:0:aspacem  1186: anon 0039fdd000-003b7dcfff     24m rwx-H
--23075:0:aspacem  1187: file 003b7dd000-003b820fff  278528 r-xT- d=0xfd03 i=145524  o=0       (458)
--23075:0:aspacem  1188: file 003b821000-003ba1ffff 2093056 ----- d=0xfd03 i=145524  o=278528  (458)
--23075:0:aspacem  1189: file 003ba20000-003ba22fff   12288 r---- d=0xfd03 i=145524  o=274432  (458)
--23075:0:aspacem  1190: file 003ba23000-003ba23fff    4096 rw--- d=0xfd03 i=145524  o=286720  (458)
--23075:0:aspacem  1191: anon 003ba24000-003ba24fff    4096 rw---
--23075:0:aspacem  1192: file 003ba25000-003ba41fff  118784 r-xT- d=0xfd03 i=145516  o=0       (459)
--23075:0:aspacem  1193: file 003ba42000-003bc40fff 2093056 ----- d=0xfd03 i=145516  o=118784  (459)
--23075:0:aspacem  1194: file 003bc41000-003bc42fff    8192 r---- d=0xfd03 i=145516  o=114688  (459)
--23075:0:aspacem  1195: file 003bc43000-003bc43fff    4096 rw--- d=0xfd03 i=145516  o=122880  (459)
--23075:0:aspacem  1196: file 003bc44000-003bc8dfff  303104 r-xT- d=0xfd03 i=145520  o=0       (460)
--23075:0:aspacem  1197: file 003bc8e000-003be8cfff 2093056 ----- d=0xfd03 i=145520  o=303104  (460)
--23075:0:aspacem  1198: file 003be8d000-003be8efff    8192 r---- d=0xfd03 i=145520  o=299008  (460)
--23075:0:aspacem  1199: file 003be8f000-003be8ffff    4096 rw--- d=0xfd03 i=145520  o=307200  (460)
--23075:0:aspacem  1200: anon 003be90000-003d68ffff     24m rwx-H
--23075:0:aspacem  1201:      003d690000-003d7e0fff 1380352
--23075:0:aspacem  1202: anon 003d7e1000-003dbe0fff 4194304 rwx-H
--23075:0:aspacem  1203: file 003dbe1000-003dbf6fff   90112 r-xT- d=0xfd03 i=144941  o=0       (304)
--23075:0:aspacem  1204: file 003dbf7000-003ddf6fff 2097152 ----- d=0xfd03 i=144941  o=90112   (304)
--23075:0:aspacem  1205: file 003ddf7000-003ddf7fff    4096 r---- d=0xfd03 i=144941  o=90112   (304)
--23075:0:aspacem  1206: file 003ddf8000-003ddf8fff    4096 rw--- d=0xfd03 i=144941  o=94208   (304)
--23075:0:aspacem  1207:      003ddf9000-003dfddfff 1986560
--23075:0:aspacem  1208: file 003dfde000-003e01ffff  270336 r-xT- d=0xfd03 i=150289  o=0       (298)
--23075:0:aspacem  1209: file 003e020000-003e21efff 2093056 ----- d=0xfd03 i=150289  o=270336  (298)
--23075:0:aspacem  1210: file 003e21f000-003e21ffff    4096 r---- d=0xfd03 i=150289  o=266240  (298)
--23075:0:aspacem  1211: file 003e220000-003e221fff    8192 rw--- d=0xfd03 i=150289  o=270336  (298)
--23075:0:aspacem  1212: anon 003e222000-003ee21fff     12m rwx-H
--23075:0:aspacem  1213: shm  003ee22000-003f360fff 5500928 rw---
--23075:0:aspacem  1214: anon 003f361000-003f760fff 4194304 rwx-H
--23075:0:aspacem  1215:      003f761000-003fa24fff 2899968
--23075:0:aspacem  1216: anon 003fa25000-003fa25fff    4096 -----
--23075:0:aspacem  1217: anon 003fa26000-0040225fff 8388608 rw---
--23075:0:aspacem  1218: anon 0040226000-0042225fff     32m rwx-H
--23075:0:aspacem  1219:      0042226000-0042229fff   16384
--23075:0:aspacem  1220: anon 004222a000-004222afff    4096 -----
--23075:0:aspacem  1221: anon 004222b000-0042a2afff 8388608 rw---
--23075:0:aspacem  1222: anon 0042a2b000-0043a2afff     16m rwx-H
--23075:0:aspacem  1223:      0043a2b000-0043a2cfff    8192
--23075:0:aspacem  1224: anon 0043a2d000-0043a2dfff    4096 -----
--23075:0:aspacem  1225: anon 0043a2e000-004422dfff 8388608 rw---
--23075:0:aspacem  1226: anon 004422e000-004422efff    4096 -----
--23075:0:aspacem  1227: anon 004422f000-0044a2efff 8388608 rw---
--23075:0:aspacem  1228: anon 0044a2f000-0046a2efff     32m rwx-H
--23075:0:aspacem  1229:      0046a2f000-0046a32fff   16384
--23075:0:aspacem  1230: anon 0046a33000-0047632fff     12m rwx-H
--23075:0:aspacem  1231:      0047633000-0047633fff    4096
--23075:0:aspacem  1232: anon 0047634000-0048633fff     16m rwx-H
--23075:0:aspacem  1233: file 0048634000-0048638fff   20480 r-xT- d=0xfd03 i=2890109 o=0       (306)
--23075:0:aspacem  1234: file 0048639000-0048837fff 2093056 ----- d=0xfd03 i=2890109 o=20480   (306)
--23075:0:aspacem  1235: file 0048838000-0048838fff    4096 r---- d=0xfd03 i=2890109 o=16384   (306)
--23075:0:aspacem  1236: file 0048839000-0048839fff    4096 rw--- d=0xfd03 i=2890109 o=20480   (306)
--23075:0:aspacem  1237: anon 004883a000-0049039fff 8388608 rwx-H
--23075:0:aspacem  1238: file 004903a000-004905bfff  139264 r-xT- d=0xfd03 i=145631  o=0       (305)
--23075:0:aspacem  1239: file 004905c000-004925bfff 2097152 ----- d=0xfd03 i=145631  o=139264  (305)
--23075:0:aspacem  1240: file 004925c000-004925dfff    8192 r---- d=0xfd03 i=145631  o=139264  (305)
--23075:0:aspacem  1241: file 004925e000-004925efff    4096 rw--- d=0xfd03 i=145631  o=147456  (305)
--23075:0:aspacem  1242: file 004925f000-00492bffff  397312 r-xT- d=0xfd03 i=16537   o=0       (308)
--23075:0:aspacem  1243: file 00492c0000-00494bffff 2097152 ----- d=0xfd03 i=16537   o=397312  (308)
--23075:0:aspacem  1244: file 00494c0000-00494c3fff   16384 r---- d=0xfd03 i=16537   o=397312  (308)
--23075:0:aspacem  1245: file 00494c4000-00494c5fff    8192 rw--- d=0xfd03 i=16537   o=413696  (308)
--23075:0:aspacem  1246: file 00494c6000-0049513fff  319488 r-xT- d=0xfd03 i=145633  o=0       (307)
--23075:0:aspacem  1247: file 0049514000-0049712fff 2093056 ----- d=0xfd03 i=145633  o=319488  (307)
--23075:0:aspacem  1248: file 0049713000-0049715fff   12288 r---- d=0xfd03 i=145633  o=315392  (307)
--23075:0:aspacem  1249: file 0049716000-0049717fff    8192 rw--- d=0xfd03 i=145633  o=327680  (307)
--23075:0:aspacem  1250: file 0049718000-0049758fff  266240 r-xT- d=0xfd03 i=145639  o=0       (309)
--23075:0:aspacem  1251: file 0049759000-0049957fff 2093056 ----- d=0xfd03 i=145639  o=266240  (309)
--23075:0:aspacem  1252: file 0049958000-0049959fff    8192 r---- d=0xfd03 i=145639  o=262144  (309)
--23075:0:aspacem  1253: file 004995a000-004995bfff    8192 rw--- d=0xfd03 i=145639  o=270336  (309)
--23075:0:aspacem  1254: file 004995c000-0049991fff  221184 r-xT- d=0xfd03 i=145619  o=0       (316)
--23075:0:aspacem  1255: file 0049992000-0049b91fff 2097152 ----- d=0xfd03 i=145619  o=221184  (316)
--23075:0:aspacem  1256: file 0049b92000-0049b93fff    8192 r---- d=0xfd03 i=145619  o=221184  (316)
--23075:0:aspacem  1257: file 0049b94000-0049b94fff    4096 rw--- d=0xfd03 i=145619  o=229376  (316)
--23075:0:aspacem  1258: file 0049b95000-0049bb8fff  147456 r-xT- d=0xfd03 i=145629  o=0       (323)
--23075:0:aspacem  1259: file 0049bb9000-0049db7fff 2093056 ----- d=0xfd03 i=145629  o=147456  (323)
--23075:0:aspacem  1260: file 0049db8000-0049db8fff    4096 r---- d=0xfd03 i=145629  o=143360  (323)
--23075:0:aspacem  1261: file 0049db9000-0049db9fff    4096 rw--- d=0xfd03 i=145629  o=147456  (323)
--23075:0:aspacem  1262: file 0049dba000-0049de2fff  167936 r-xT- d=0xfd03 i=145597  o=0       (330)
--23075:0:aspacem  1263: file 0049de3000-0049fe2fff 2097152 ----- d=0xfd03 i=145597  o=167936  (330)
--23075:0:aspacem  1264: file 0049fe3000-0049fe3fff    4096 r---- d=0xfd03 i=145597  o=167936  (330)
--23075:0:aspacem  1265: file 0049fe4000-0049fe4fff    4096 rw--- d=0xfd03 i=145597  o=172032  (330)
--23075:0:aspacem  1266: file 0049fe5000-0049ff5fff   69632 r-xT- d=0xfd03 i=145613  o=0       (337)
--23075:0:aspacem  1267: file 0049ff6000-004a1f5fff 2097152 ----- d=0xfd03 i=145613  o=69632   (337)
--23075:0:aspacem  1268: file 004a1f6000-004a1f6fff    4096 r---- d=0xfd03 i=145613  o=69632   (337)
--23075:0:aspacem  1269: file 004a1f7000-004a1f7fff    4096 rw--- d=0xfd03 i=145613  o=73728   (337)
--23075:0:aspacem  1270: file 004a1f8000-004a208fff   69632 r-xT- d=0xfd03 i=145591  o=0       (344)
--23075:0:aspacem  1271: file 004a209000-004a407fff 2093056 ----- d=0xfd03 i=145591  o=69632   (344)
--23075:0:aspacem  1272: file 004a408000-004a408fff    4096 r---- d=0xfd03 i=145591  o=65536   (344)
--23075:0:aspacem  1273: file 004a409000-004a409fff    4096 rw--- d=0xfd03 i=145591  o=69632   (344)
--23075:0:aspacem  1274: file 004a40a000-004a429fff  131072 r-xT- d=0xfd03 i=145615  o=0       (351)
--23075:0:aspacem  1275: file 004a42a000-004a628fff 2093056 ----- d=0xfd03 i=145615  o=131072  (351)
--23075:0:aspacem  1276: file 004a629000-004a62afff    8192 r---- d=0xfd03 i=145615  o=126976  (351)
--23075:0:aspacem  1277: file 004a62b000-004a62bfff    4096 rw--- d=0xfd03 i=145615  o=135168  (351)
--23075:0:aspacem  1278: file 004a62c000-004a744fff 1150976 r-xT- d=0xfd03 i=162861  o=0       (353)
--23075:0:aspacem  1279: file 004a745000-004a944fff 2097152 ----- d=0xfd03 i=162861  o=1150976 (353)
--23075:0:aspacem  1280: file 004a945000-004a94cfff   32768 r---- d=0xfd03 i=162861  o=1150976 (353)
--23075:0:aspacem  1281: file 004a94d000-004a94ffff   12288 rw--- d=0xfd03 i=162861  o=1183744 (353)
--23075:0:aspacem  1282: file 004a950000-004a977fff  163840 r-xT- d=0xfd03 i=145603  o=0       (359)
--23075:0:aspacem  1283: file 004a978000-004ab77fff 2097152 ----- d=0xfd03 i=145603  o=163840  (359)
--23075:0:aspacem  1284: file 004ab78000-004ab79fff    8192 r---- d=0xfd03 i=145603  o=163840  (359)
--23075:0:aspacem  1285: file 004ab7a000-004ab7afff    4096 rw--- d=0xfd03 i=145603  o=172032  (359)
--23075:0:aspacem  1286: file 004ab7b000-004ab93fff  102400 r-xT- d=0xfd03 i=145628  o=0       (366)
--23075:0:aspacem  1287: file 004ab94000-004ad93fff 2097152 ----- d=0xfd03 i=145628  o=102400  (366)
--23075:0:aspacem  1288: file 004ad94000-004ad94fff    4096 r---- d=0xfd03 i=145628  o=102400  (366)
--23075:0:aspacem  1289: file 004ad95000-004ad95fff    4096 rw--- d=0xfd03 i=145628  o=106496  (366)
--23075:0:aspacem  1290: file 004ad96000-004adbcfff  159744 r-xT- d=0xfd03 i=102667  o=0       (368)
--23075:0:aspacem  1291: file 004adbd000-004afbbfff 2093056 ----- d=0xfd03 i=102667  o=159744  (368)
--23075:0:aspacem  1292: file 004afbc000-004afbcfff    4096 r---- d=0xfd03 i=102667  o=155648  (368)
--23075:0:aspacem  1293: file 004afbd000-004afbdfff    4096 rw--- d=0xfd03 i=102667  o=159744  (368)
--23075:0:aspacem  1294: file 004afbe000-004afd9fff  114688 r-xT- d=0xfd03 i=145601  o=0       (374)
--23075:0:aspacem  1295: file 004afda000-004b1d8fff 2093056 ----- d=0xfd03 i=145601  o=114688  (374)
--23075:0:aspacem  1296: file 004b1d9000-004b1dafff    8192 r---- d=0xfd03 i=145601  o=110592  (374)
--23075:0:aspacem  1297: file 004b1db000-004b1dbfff    4096 rw--- d=0xfd03 i=145601  o=118784  (374)
--23075:0:aspacem  1298: file 004b1dc000-004b237fff  376832 r-xT- d=0xfd03 i=145641  o=0       (375)
--23075:0:aspacem  1299: file 004b238000-004b437fff 2097152 ----- d=0xfd03 i=145641  o=376832  (375)
--23075:0:aspacem  1300: file 004b438000-004b43cfff   20480 r---- d=0xfd03 i=145641  o=376832  (375)
--23075:0:aspacem  1301: file 004b43d000-004b43dfff    4096 rw--- d=0xfd03 i=145641  o=397312  (375)
--23075:0:aspacem  1302: file 004b43e000-004b456fff  102400 r-xT- d=0xfd03 i=145637  o=0       (382)
--23075:0:aspacem  1303: file 004b457000-004b655fff 2093056 ----- d=0xfd03 i=145637  o=102400  (382)
--23075:0:aspacem  1304: file 004b656000-004b657fff    8192 r---- d=0xfd03 i=145637  o=98304   (382)
--23075:0:aspacem  1305: file 004b658000-004b658fff    4096 rw--- d=0xfd03 i=145637  o=106496  (382)
--23075:0:aspacem  1306: file 004b659000-004b6dcfff  540672 r-xT- d=0xfd03 i=145607  o=0       (389)
--23075:0:aspacem  1307: file 004b6dd000-004b8dbfff 2093056 ----- d=0xfd03 i=145607  o=540672  (389)
--23075:0:aspacem  1308: file 004b8dc000-004b8e1fff   24576 r---- d=0xfd03 i=145607  o=536576  (389)
--23075:0:aspacem  1309: file 004b8e2000-004b8e3fff    8192 rw--- d=0xfd03 i=145607  o=561152  (389)
--23075:0:aspacem  1310: file 004b8e4000-004b918fff  217088 r-xT- d=0xfd03 i=145622  o=0       (390)
--23075:0:aspacem  1311: file 004b919000-004bb17fff 2093056 ----- d=0xfd03 i=145622  o=217088  (390)
--23075:0:aspacem  1312: file 004bb18000-004bb19fff    8192 r---- d=0xfd03 i=145622  o=212992  (390)
--23075:0:aspacem  1313: file 004bb1a000-004bb1afff    4096 rw--- d=0xfd03 i=145622  o=221184  (390)
--23075:0:aspacem  1314: file 004bb1b000-004bb38fff  122880 r-xT- d=0xfd03 i=145605  o=0       (397)
--23075:0:aspacem  1315: file 004bb39000-004bd37fff 2093056 ----- d=0xfd03 i=145605  o=122880  (397)
--23075:0:aspacem  1316: file 004bd38000-004bd39fff    8192 r---- d=0xfd03 i=145605  o=118784  (397)
--23075:0:aspacem  1317: file 004bd3a000-004bd3afff    4096 rw--- d=0xfd03 i=145605  o=126976  (397)
--23075:0:aspacem  1318: file 004bd3b000-004bd69fff  192512 r-xT- d=0xfd03 i=145634  o=0       (404)
--23075:0:aspacem  1319: file 004bd6a000-004bf69fff 2097152 ----- d=0xfd03 i=145634  o=192512  (404)
--23075:0:aspacem  1320: file 004bf6a000-004bf6afff    4096 r---- d=0xfd03 i=145634  o=192512  (404)
--23075:0:aspacem  1321: file 004bf6b000-004bf6bfff    4096 rw--- d=0xfd03 i=145634  o=196608  (404)
--23075:0:aspacem  1322: file 004bf6c000-004bf86fff  110592 r-xT- d=0xfd03 i=145617  o=0       (411)
--23075:0:aspacem  1323: file 004bf87000-004c186fff 2097152 ----- d=0xfd03 i=145617  o=110592  (411)
--23075:0:aspacem  1324: file 004c187000-004c187fff    4096 r---- d=0xfd03 i=145617  o=110592  (411)
--23075:0:aspacem  1325: file 004c188000-004c188fff    4096 rw--- d=0xfd03 i=145617  o=114688  (411)
--23075:0:aspacem  1326: file 004c189000-004c30efff 1597440 r-xT- d=0xfd03 i=145593  o=0       (412)
--23075:0:aspacem  1327: file 004c30f000-004c50dfff 2093056 ----- d=0xfd03 i=145593  o=1597440 (412)
--23075:0:aspacem  1328: file 004c50e000-004c51efff   69632 r---- d=0xfd03 i=145593  o=1593344 (412)
--23075:0:aspacem  1329: file 004c51f000-004c521fff   12288 rw--- d=0xfd03 i=145593  o=1662976 (412)
--23075:0:aspacem  1330: file 004c522000-004c551fff  196608 r-xT- d=0xfd03 i=145640  o=0       (413)
--23075:0:aspacem  1331: file 004c552000-004c750fff 2093056 ----- d=0xfd03 i=145640  o=196608  (413)
--23075:0:aspacem  1332: file 004c751000-004c753fff   12288 r---- d=0xfd03 i=145640  o=192512  (413)
--23075:0:aspacem  1333: file 004c754000-004c754fff    4096 rw--- d=0xfd03 i=145640  o=204800  (413)
--23075:0:aspacem  1334: file 004c755000-004c769fff   86016 r-xT- d=0xfd03 i=42225   o=0       (415)
--23075:0:aspacem  1335: file 004c76a000-004c968fff 2093056 ----- d=0xfd03 i=42225   o=86016   (415)
--23075:0:aspacem  1336: file 004c969000-004c969fff    4096 r---- d=0xfd03 i=42225   o=81920   (415)
--23075:0:aspacem  1337: file 004c96a000-004c96afff    4096 rw--- d=0xfd03 i=42225   o=86016   (415)
--23075:0:aspacem  1338: file 004c96b000-004c9a4fff  237568 r-xT- d=0xfd03 i=42226   o=0       (416)
--23075:0:aspacem  1339: file 004c9a5000-004cba4fff 2097152 ----- d=0xfd03 i=42226   o=237568  (416)
--23075:0:aspacem  1340: file 004cba5000-004cba5fff    4096 r---- d=0xfd03 i=42226   o=237568  (416)
--23075:0:aspacem  1341: file 004cba6000-004cba6fff    4096 rw--- d=0xfd03 i=42226   o=241664  (416)
--23075:0:aspacem  1342: anon 004cba7000-004cba7fff    4096 rw---
--23075:0:aspacem  1343: file 004cba8000-004cc25fff  516096 r-xT- d=0xfd03 i=18008   o=0       (417)
--23075:0:aspacem  1344: file 004cc26000-004ce25fff 2097152 ----- d=0xfd03 i=18008   o=516096  (417)
--23075:0:aspacem  1345: file 004ce26000-004ce26fff    4096 r---- d=0xfd03 i=18008   o=516096  (417)
--23075:0:aspacem  1346: file 004ce27000-004ce29fff   12288 rw--- d=0xfd03 i=18008   o=520192  (417)
--23075:0:aspacem  1347: file 004ce2a000-004ce2dfff   16384 r-xT- d=0xfd03 i=102057  o=0       (418)
--23075:0:aspacem  1348: file 004ce2e000-004d02cfff 2093056 ----- d=0xfd03 i=102057  o=16384   (418)
--23075:0:aspacem  1349: file 004d02d000-004d02dfff    4096 r---- d=0xfd03 i=102057  o=12288   (418)
--23075:0:aspacem  1350: file 004d02e000-004d02efff    4096 rw--- d=0xfd03 i=102057  o=16384   (418)
--23075:0:aspacem  1351: file 004d02f000-004d04afff  114688 r-xT- d=0xfd03 i=145638  o=0       (414)
--23075:0:aspacem  1352: file 004d04b000-004d24afff 2097152 ----- d=0xfd03 i=145638  o=114688  (414)
--23075:0:aspacem  1353: file 004d24b000-004d24bfff    4096 r---- d=0xfd03 i=145638  o=114688  (414)
--23075:0:aspacem  1354: file 004d24c000-004d24cfff    4096 rw--- d=0xfd03 i=145638  o=118784  (414)
--23075:0:aspacem  1355: file 004d24d000-004d426fff 1941504 r-xT- d=0xfd03 i=145595  o=0       (425)
--23075:0:aspacem  1356: file 004d427000-004d626fff 2097152 ----- d=0xfd03 i=145595  o=1941504 (425)
--23075:0:aspacem  1357: file 004d627000-004d630fff   40960 r---- d=0xfd03 i=145595  o=1941504 (425)
--23075:0:aspacem  1358: file 004d631000-004d634fff   16384 rw--- d=0xfd03 i=145595  o=1982464 (425)
--23075:0:aspacem  1359: anon 004d635000-004d635fff    4096 rw---
--23075:0:aspacem  1360: file 004d636000-004d6a8fff  471040 r-xT- d=0xfd03 i=145636  o=0       (426)
--23075:0:aspacem  1361: file 004d6a9000-004d8a7fff 2093056 ----- d=0xfd03 i=145636  o=471040  (426)
--23075:0:aspacem  1362: file 004d8a8000-004d8adfff   24576 r---- d=0xfd03 i=145636  o=466944  (426)
--23075:0:aspacem  1363: file 004d8ae000-004d8aefff    4096 rw--- d=0xfd03 i=145636  o=491520  (426)
--23075:0:aspacem  1364: file 004d8af000-004d9c5fff 1142784 r-xT- d=0xfd03 i=145624  o=0       (427)
--23075:0:aspacem  1365: file 004d9c6000-004dbc4fff 2093056 ----- d=0xfd03 i=145624  o=1142784 (427)
--23075:0:aspacem  1366: file 004dbc5000-004dbcafff   24576 r---- d=0xfd03 i=145624  o=1138688 (427)
--23075:0:aspacem  1367: file 004dbcb000-004dbcefff   16384 rw--- d=0xfd03 i=145624  o=1163264 (427)
--23075:0:aspacem  1368: anon 004dbcf000-004dbcffff    4096 rw---
--23075:0:aspacem  1369: file 004dbd0000-0051bd0fff     64m rw--- d=0x00e i=23657813 o=0       (280)
--23075:0:aspacem  1370: anon 0051bd1000-007ebd0fff    720m rwx-H
--23075:0:aspacem  1371:      007ebd1000-007ecd1fff 1052672
--23075:0:aspacem  1372: anon 007ecd2000-00860d1fff    116m rwx-H
--23075:0:aspacem  1373:      00860d2000-00862d2fff 2101248
--23075:0:aspacem  1374: anon 00862d3000-008b2d2fff     80m rwx-H
--23075:0:aspacem  1375:      008b2d3000-008b3d0fff 1040384
--23075:0:aspacem  1376: anon 008b3d1000-00973d0fff    192m rwx-H
--23075:0:aspacem  1377:      00973d1000-00974d1fff 1052672
--23075:0:aspacem  1378: anon 00974d2000-00a28d1fff    180m rwx-H
--23075:0:aspacem  1379:      00a28d2000-00a2ad2fff 2101248
--23075:0:aspacem  1380: anon 00a2ad3000-00af2d2fff    200m rwx-H
--23075:0:aspacem  1381:      00af2d3000-00af2d3fff    4096
--23075:0:aspacem  1382: anon 00af2d4000-00cdad3fff    488m rwx-H
--23075:0:aspacem  1383:      00cdad4000-00cdad4fff    4096
--23075:0:aspacem  1384: anon 00cdad5000-0146ed4fff   1940m rwx-H
--23075:0:aspacem  1385:      0146ed5000-0146ed5fff    4096
--23075:0:aspacem  1386: anon 0146ed6000-01542d5fff    212m rwx-H
--23075:0:aspacem  1387:      01542d6000-01542d6fff    4096
--23075:0:aspacem  1388: anon 01542d7000-01746d6fff    516m rwx-H
--23075:0:aspacem  1389:      01746d7000-01746d7fff    4096
--23075:0:aspacem  1390: anon 01746d8000-01e3ed8fff   1784m rwx-H
--23075:0:aspacem  1391:      01e3ed9000-01f540ffff    277m
--23075:0:aspacem  1392: anon 01f5410000-02a040ffff   2736m rwx-H
--23075:0:aspacem  1393:      02a0410000-0801ffffff  22043m
--23075:0:aspacem  1394: RSVN 0802000000-0802000fff    4096 ----- SmFixed
--23075:0:aspacem  1395: ANON 0802001000-0802dd4fff     13m rwx--
--23075:0:aspacem  1396: FILE 0802dd5000-0802dd5fff    4096 rw--- d=0xfd06 i=45      o=0       (3)
--23075:0:aspacem  1397: ANON 0802dd6000-08039e3fff     12m rwx--
--23075:0:aspacem  1398: ANON 08039e4000-08039e5fff    8192 -----
--23075:0:aspacem  1399: ANON 08039e6000-0803ae5fff 1048576 rwx--
--23075:0:aspacem  1400: ANON 0803ae6000-0803ae7fff    8192 -----
--23075:0:aspacem  1401: ANON 0803ae8000-080b7c4fff    124m rwx--
--23075:0:aspacem  1402:      080b7c5000-080b7c5fff    4096
--23075:0:aspacem  1403: ANON 080b7c6000-080d656fff     30m rwx--
--23075:0:aspacem  1404:      080d657000-080d657fff    4096
--23075:0:aspacem  1405: ANON 080d658000-080de56fff 8384512 rwx--
--23075:0:aspacem  1406:      080de57000-080de57fff    4096
--23075:0:aspacem  1407: ANON 080de58000-080f125fff     18m rwx--
--23075:0:aspacem  1408:      080f126000-080f128fff   12288
--23075:0:aspacem  1409: ANON 080f129000-08102c0fff     17m rwx--
--23075:0:aspacem  1410:      08102c1000-08102c2fff    8192
--23075:0:aspacem  1411: ANON 08102c3000-08102eafff  163840 rwx--
--23075:0:aspacem  1412:      08102eb000-08102edfff   12288
--23075:0:aspacem  1413: ANON 08102ee000-0810597fff 2793472 rwx--
--23075:0:aspacem  1414:      0810598000-0810598fff    4096
--23075:0:aspacem  1415: ANON 0810599000-0810a4afff 4923392 rwx--
--23075:0:aspacem  1416:      0810a4b000-0810a4bfff    4096
--23075:0:aspacem  1417: ANON 0810a4c000-08119cefff     15m rwx--
--23075:0:aspacem  1418:      08119cf000-08119d0fff    8192
--23075:0:aspacem  1419: ANON 08119d1000-0811a78fff  688128 rwx--
--23075:0:aspacem  1420:      0811a79000-0811a7bfff   12288
--23075:0:aspacem  1421: ANON 0811a7c000-0812b00fff     16m rwx--
--23075:0:aspacem  1422:      0812b01000-0812b03fff   12288
--23075:0:aspacem  1423: ANON 0812b04000-0813fc9fff     20m rwx--
--23075:0:aspacem  1424:      0813fca000-0813fcafff    4096
--23075:0:aspacem  1425: ANON 0813fcb000-0814e24fff     14m rwx--
--23075:0:aspacem  1426:      0814e25000-0814e26fff    8192
--23075:0:aspacem  1427: ANON 0814e27000-0814e7afff  344064 rwx--
--23075:0:aspacem  1428:      0814e7b000-0814e7dfff   12288
--23075:0:aspacem  1429: ANON 0814e7e000-0814e81fff   16384 rwx--
--23075:0:aspacem  1430:      0814e82000-0814e83fff    8192
--23075:0:aspacem  1431: ANON 0814e84000-08163dffff     21m rwx--
--23075:0:aspacem  1432:      08163e0000-08163e0fff    4096
--23075:0:aspacem  1433: ANON 08163e1000-0816729fff 3444736 rwx--
--23075:0:aspacem  1434:      081672a000-081672afff    4096
--23075:0:aspacem  1435: ANON 081672b000-081e1a4fff    122m rwx--
--23075:0:aspacem  1436:      081e1a5000-081e1a5fff    4096
--23075:0:aspacem  1437: ANON 081e1a6000-081f068fff     14m rwx--
--23075:0:aspacem  1438:      081f069000-081f069fff    4096
--23075:0:aspacem  1439: ANON 081f06a000-0822d88fff     61m rwx--
--23075:0:aspacem  1440:      0822d89000-0822d8bfff   12288
--23075:0:aspacem  1441: ANON 0822d8c000-08257e9fff     42m rwx--
--23075:0:aspacem  1442: ANON 08257ea000-08257ebfff    8192 -----
--23075:0:aspacem  1443: ANON 08257ec000-08258ebfff 1048576 rwx--
--23075:0:aspacem  1444: ANON 08258ec000-08258edfff    8192 -----
--23075:0:aspacem  1445: ANON 08258ee000-082591dfff  196608 rwx--
--23075:0:aspacem  1446: ANON 082591e000-082591ffff    8192 -----
--23075:0:aspacem  1447: ANON 0825920000-0825a1ffff 1048576 rwx--
--23075:0:aspacem  1448: ANON 0825a20000-0825a21fff    8192 -----
--23075:0:aspacem  1449: ANON 0825a22000-0825a69fff  294912 rwx--
--23075:0:aspacem  1450: ANON 0825a6a000-0825a6bfff    8192 -----
--23075:0:aspacem  1451: ANON 0825a6c000-0825b6bfff 1048576 rwx--
--23075:0:aspacem  1452: ANON 0825b6c000-0825b6dfff    8192 -----
--23075:0:aspacem  1453: ANON 0825b6e000-0825cd5fff 1474560 rwx--
--23075:0:aspacem  1454:      0825cd6000-0825cd8fff   12288
--23075:0:aspacem  1455: ANON 0825cd9000-0825dacfff  868352 rwx--
--23075:0:aspacem  1456:      0825dad000-0825dadfff    4096
--23075:0:aspacem  1457: ANON 0825dae000-082ab45fff     77m rwx--
--23075:0:aspacem  1458:      082ab46000-082ab48fff   12288
--23075:0:aspacem  1459: ANON 082ab49000-082d3eefff     40m rwx--
--23075:0:aspacem  1460: ANON 082d3ef000-082d3f0fff    8192 -----
--23075:0:aspacem  1461: ANON 082d3f1000-082d4f0fff 1048576 rwx--
--23075:0:aspacem  1462: ANON 082d4f1000-082d4f2fff    8192 -----
--23075:0:aspacem  1463: ANON 082d4f3000-082d52afff  229376 rwx--
--23075:0:aspacem  1464:      082d52b000-082d52cfff    8192
--23075:0:aspacem  1465: ANON 082d52d000-082d8b8fff 3719168 rwx--
--23075:0:aspacem  1466: ANON 082d8b9000-082d8bafff    8192 -----
--23075:0:aspacem  1467: ANON 082d8bb000-082d9bafff 1048576 rwx--
--23075:0:aspacem  1468: ANON 082d9bb000-082d9bcfff    8192 -----
--23075:0:aspacem  1469: ANON 082d9bd000-082de04fff 4489216 rwx--
--23075:0:aspacem  1470:      082de05000-082de07fff   12288
--23075:0:aspacem  1471: ANON 082de08000-082e263fff 4571136 rwx--
--23075:0:aspacem  1472:      082e264000-082e265fff    8192
--23075:0:aspacem  1473: ANON 082e266000-082e2a5fff  262144 rwx--
--23075:0:aspacem  1474:      082e2a6000-082e2a8fff   12288
--23075:0:aspacem  1475: ANON 082e2a9000-08326effff     68m rwx--
--23075:0:aspacem  1476: ANON 08326f0000-08326f1fff    8192 -----
--23075:0:aspacem  1477: ANON 08326f2000-08327f1fff 1048576 rwx--
--23075:0:aspacem  1478: ANON 08327f2000-08327f3fff    8192 -----
--23075:0:aspacem  1479: ANON 08327f4000-08327f7fff   16384 rwx--
--23075:0:aspacem  1480: ANON 08327f8000-08327f9fff    8192 -----
--23075:0:aspacem  1481: ANON 08327fa000-08328f9fff 1048576 rwx--
--23075:0:aspacem  1482: ANON 08328fa000-08328fbfff    8192 -----
--23075:0:aspacem  1483: ANON 08328fc000-08328fffff   16384 rwx--
--23075:0:aspacem  1484: ANON 0832900000-0832901fff    8192 -----
--23075:0:aspacem  1485: ANON 0832902000-0832a01fff 1048576 rwx--
--23075:0:aspacem  1486: ANON 0832a02000-0832a03fff    8192 -----
--23075:0:aspacem  1487: ANON 0832a04000-0832a0ffff   49152 rwx--
--23075:0:aspacem  1488: ANON 0832a10000-0832a11fff    8192 -----
--23075:0:aspacem  1489: ANON 0832a12000-0832b11fff 1048576 rwx--
--23075:0:aspacem  1490: ANON 0832b12000-0832b13fff    8192 -----
--23075:0:aspacem  1491: ANON 0832b14000-0832b2ffff  114688 rwx--
--23075:0:aspacem  1492: ANON 0832b30000-0832b31fff    8192 -----
--23075:0:aspacem  1493: ANON 0832b32000-0832c31fff 1048576 rwx--
--23075:0:aspacem  1494: ANON 0832c32000-0832c33fff    8192 -----
--23075:0:aspacem  1495: ANON 0832c34000-0832c3ffff   49152 rwx--
--23075:0:aspacem  1496: ANON 0832c40000-0832c41fff    8192 -----
--23075:0:aspacem  1497: ANON 0832c42000-0832d41fff 1048576 rwx--
--23075:0:aspacem  1498: ANON 0832d42000-0832d43fff    8192 -----
--23075:0:aspacem  1499: ANON 0832d44000-0832d47fff   16384 rwx--
--23075:0:aspacem  1500: ANON 0832d48000-0832d49fff    8192 -----
--23075:0:aspacem  1501: ANON 0832d4a000-0832e49fff 1048576 rwx--
--23075:0:aspacem  1502: ANON 0832e4a000-0832e4bfff    8192 -----
--23075:0:aspacem  1503: ANON 0832e4c000-0832e4ffff   16384 rwx--
--23075:0:aspacem  1504: ANON 0832e50000-0832e51fff    8192 -----
--23075:0:aspacem  1505: ANON 0832e52000-0832f51fff 1048576 rwx--
--23075:0:aspacem  1506: ANON 0832f52000-0832f53fff    8192 -----
--23075:0:aspacem  1507: ANON 0832f54000-0832f57fff   16384 rwx--
--23075:0:aspacem  1508: ANON 0832f58000-0832f59fff    8192 -----
--23075:0:aspacem  1509: ANON 0832f5a000-0833059fff 1048576 rwx--
--23075:0:aspacem  1510: ANON 083305a000-083305bfff    8192 -----
--23075:0:aspacem  1511: ANON 083305c000-0833063fff   32768 rwx--
--23075:0:aspacem  1512: ANON 0833064000-0833065fff    8192 -----
--23075:0:aspacem  1513: ANON 0833066000-0833165fff 1048576 rwx--
--23075:0:aspacem  1514: ANON 0833166000-0833167fff    8192 -----
--23075:0:aspacem  1515: ANON 0833168000-083316bfff   16384 rwx--
--23075:0:aspacem  1516: ANON 083316c000-083316dfff    8192 -----
--23075:0:aspacem  1517: ANON 083316e000-083326dfff 1048576 rwx--
--23075:0:aspacem  1518: ANON 083326e000-083326ffff    8192 -----
--23075:0:aspacem  1519: ANON 0833270000-0833333fff  802816 rwx--
--23075:0:aspacem  1520: ANON 0833334000-0833335fff    8192 -----
--23075:0:aspacem  1521: ANON 0833336000-0833435fff 1048576 rwx--
--23075:0:aspacem  1522: ANON 0833436000-0833437fff    8192 -----
--23075:0:aspacem  1523: ANON 0833438000-083343bfff   16384 rwx--
--23075:0:aspacem  1524: ANON 083343c000-083343dfff    8192 -----
--23075:0:aspacem  1525: ANON 083343e000-083353dfff 1048576 rwx--
--23075:0:aspacem  1526: ANON 083353e000-083353ffff    8192 -----
--23075:0:aspacem  1527: ANON 0833540000-0833543fff   16384 rwx--
--23075:0:aspacem  1528: ANON 0833544000-0833545fff    8192 -----
--23075:0:aspacem  1529: ANON 0833546000-0833645fff 1048576 rwx--
--23075:0:aspacem  1530: ANON 0833646000-0833647fff    8192 -----
--23075:0:aspacem  1531: ANON 0833648000-083364bfff   16384 rwx--
--23075:0:aspacem  1532: ANON 083364c000-083364dfff    8192 -----
--23075:0:aspacem  1533: ANON 083364e000-083374dfff 1048576 rwx--
--23075:0:aspacem  1534: ANON 083374e000-083374ffff    8192 -----
--23075:0:aspacem  1535: ANON 0833750000-083376ffff  131072 rwx--
--23075:0:aspacem  1536: ANON 0833770000-0833771fff    8192 -----
--23075:0:aspacem  1537: ANON 0833772000-0833871fff 1048576 rwx--
--23075:0:aspacem  1538: ANON 0833872000-0833873fff    8192 -----
--23075:0:aspacem  1539: ANON 0833874000-083388bfff   98304 rwx--
--23075:0:aspacem  1540: ANON 083388c000-083388dfff    8192 -----
--23075:0:aspacem  1541: ANON 083388e000-083398dfff 1048576 rwx--
--23075:0:aspacem  1542: ANON 083398e000-083398ffff    8192 -----
--23075:0:aspacem  1543: ANON 0833990000-083399bfff   49152 rwx--
--23075:0:aspacem  1544: ANON 083399c000-083399dfff    8192 -----
--23075:0:aspacem  1545: ANON 083399e000-0833a9dfff 1048576 rwx--
--23075:0:aspacem  1546: ANON 0833a9e000-0833a9ffff    8192 -----
--23075:0:aspacem  1547: ANON 0833aa0000-0833aa7fff   32768 rwx--
--23075:0:aspacem  1548: ANON 0833aa8000-0833aa9fff    8192 -----
--23075:0:aspacem  1549: ANON 0833aaa000-0833ba9fff 1048576 rwx--
--23075:0:aspacem  1550: ANON 0833baa000-0833babfff    8192 -----
--23075:0:aspacem  1551: ANON 0833bac000-0833baffff   16384 rwx--
--23075:0:aspacem  1552: ANON 0833bb0000-0833bb1fff    8192 -----
--23075:0:aspacem  1553: ANON 0833bb2000-0833cb1fff 1048576 rwx--
--23075:0:aspacem  1554: ANON 0833cb2000-0833cb3fff    8192 -----
--23075:0:aspacem  1555: ANON 0833cb4000-0833cb7fff   16384 rwx--
--23075:0:aspacem  1556: ANON 0833cb8000-0833cb9fff    8192 -----
--23075:0:aspacem  1557: ANON 0833cba000-0833db9fff 1048576 rwx--
--23075:0:aspacem  1558: ANON 0833dba000-0833dbbfff    8192 -----
--23075:0:aspacem  1559: ANON 0833dbc000-0833deffff  212992 rwx--
--23075:0:aspacem  1560: ANON 0833df0000-0833df1fff    8192 -----
--23075:0:aspacem  1561: ANON 0833df2000-0833ef1fff 1048576 rwx--
--23075:0:aspacem  1562: ANON 0833ef2000-0833ef3fff    8192 -----
--23075:0:aspacem  1563: ANON 0833ef4000-0833fb7fff  802816 rwx--
--23075:0:aspacem  1564:      0833fb8000-0833fbafff   12288
--23075:0:aspacem  1565: ANON 0833fbb000-08348fefff 9715712 rwx--
--23075:0:aspacem  1566:      08348ff000-0834900fff    8192
--23075:0:aspacem  1567: ANON 0834901000-0834928fff  163840 rwx--
--23075:0:aspacem  1568:      0834929000-083492bfff   12288
--23075:0:aspacem  1569: ANON 083492c000-083532bfff     10m rwx--
--23075:0:aspacem  1570:      083532c000-083532cfff    4096
--23075:0:aspacem  1571: ANON 083532d000-083868ffff     51m rwx--
--23075:0:aspacem  1572:      0838690000-0838691fff    8192
--23075:0:aspacem  1573: ANON 0838692000-08388bdfff 2277376 rwx--
--23075:0:aspacem  1574:      08388be000-08388c0fff   12288
--23075:0:aspacem  1575: ANON 08388c1000-0838998fff  884736 rwx--
--23075:0:aspacem  1576:      0838999000-083899bfff   12288
--23075:0:aspacem  1577: ANON 083899c000-0838a03fff  425984 rwx--
--23075:0:aspacem  1578:      0838a04000-0838a06fff   12288
--23075:0:aspacem  1579: ANON 0838a07000-0838e22fff 4308992 rwx--
--23075:0:aspacem  1580:      0838e23000-0838e23fff    4096
--23075:0:aspacem  1581: ANON 0838e24000-083cdf4fff     63m rwx--
--23075:0:aspacem  1582:      083cdf5000-083cdf7fff   12288
--23075:0:aspacem  1583: ANON 083cdf8000-083d6cbfff 9256960 rwx--
--23075:0:aspacem  1584:      083d6cc000-083d6ccfff    4096
--23075:0:aspacem  1585: ANON 083d6cd000-083ddf4fff 7503872 rwx--
--23075:0:aspacem  1586:      083ddf5000-083ddf7fff   12288
--23075:0:aspacem  1587: ANON 083ddf8000-08550f3fff    370m rwx--
--23075:0:aspacem  1588:      08550f4000-08550f4fff    4096
--23075:0:aspacem  1589: ANON 08550f5000-085dbc8fff    138m rwx--
--23075:0:aspacem  1590:      085dbc9000-085dbc9fff    4096
--23075:0:aspacem  1591: ANON 085dbca000-089027afff    806m rwx--
--23075:0:aspacem  1592:      089027b000-089027cfff    8192
--23075:0:aspacem  1593: ANON 089027d000-08b7044fff    621m rwx--
--23075:0:aspacem  1594:      08b7045000-08b9c9efff     44m
--23075:0:aspacem  1595: ANON 08b9c9f000-08dab81fff    526m rwx--
--23075:0:aspacem  1596:      08dab82000-0ffe800fff  29244m
--23075:0:aspacem  1597: RSVN 0ffe801000-0ffefebfff 8302592 ----- SmUpper
--23075:0:aspacem  1598: anon 0ffefec000-0fff000fff   86016 rw---
--23075:0:aspacem  1599:      0fff001000-0fffffffff     15m
--23075:0:aspacem  1600: RSVN 1000000000-7fff9fdd8fff 131006g ----- SmFixed
--23075:0:aspacem  1601: ANON 7fff9fdd9000-7fff9fdfafff  139264 rw---
--23075:0:aspacem  1602: RSVN 7fff9fdfb000-ffffffffff5fffff  16383e ----- SmFixed
--23075:0:aspacem  1603: ANON ffffffffff600000-ffffffffff600fff    4096 r-x--
--23075:0:aspacem  1604: RSVN ffffffffff601000-ffffffffffffffff      9m ----- SmFixed
--23075:0:aspacem  >>>
--23075-- core    : 358621184/358621184  max/curr mmap'd, 3/12 unsplit/split sb unmmap'd,  347465616/347465520 max/curr,     4834792/1754823776 totalloc-blocks/bytes,     4555697 searches 8 rzB
--23075-- dinfo   : 493404160/483151872  max/curr mmap'd, 126/104 unsplit/split sb unmmap'd,  490909072/479310080 max/curr,     2350704/1775313872 totalloc-blocks/bytes,     2373341 searches 8 rzB
--23075-- client  : 10243391488/9948508160  max/curr mmap'd, 11/972 unsplit/split sb unmmap'd,  9735185536/9558754592 max/curr,    17475134/20238775184 totalloc-blocks/bytes,    36143108 searches 24 rzB
--23075-- demangle:        0/       0  max/curr mmap'd, 0/0 unsplit/split sb unmmap'd,         0/       0 max/curr,           0/         0 totalloc-blocks/bytes,           0 searches 8 rzB
--23075-- ttaux   : 11374592/11042816  max/curr mmap'd, 50/5 unsplit/split sb unmmap'd,  10950016/10560112 max/curr,       31698/  30110272 totalloc-blocks/bytes,       31602 searches 8 rzB
==23075== 
==23075==     Valgrind's memory management: out of memory:
==23075==        memcheck:allocate new SecMap's request for 16384 bytes failed.
==23075==        13634809856 bytes have already been allocated.
==23075==     Valgrind cannot continue.  Sorry.
==23075== 
==23075==     There are several possible reasons for this.
==23075==     - You have some kind of memory limit in place.  Look at the
==23075==       output of 'ulimit -a'.  Is there a limit on the size of
==23075==       virtual memory or address space?
==23075==     - You have run out of swap space.
==23075==     - Valgrind has a bug.  If you think this is the case or you are
==23075==     not sure, please let us know and we'll try to fix it.
==23075==     Please note that programs can take substantially more memory than
==23075==     normal when running under Valgrind tools, eg. up to twice or
==23075==     more, depending on the tool.  On a 64-bit machine, Valgrind
==23075==     should be able to make use of up 32GB memory.  On a 32-bit
==23075==     machine, Valgrind should be able to use all the memory available
==23075==     to a single process, up to 4GB if that's how you have your
==23075==     kernel configured.  Most 32-bit Linux setups allow a maximum of
==23075==     3GB per process.
==23075== 
==23075==     Whatever the reason, Valgrind cannot continue.  Sorry.
ca@puolukka ~ $ 

I'm wondering if I should try to run the valgrind again but first switch off the swaps, because it is very slow in valgrind with all the disk swapping going on...

Looking forward to your suggestions on how I can improve this debug information!
Comment 4 Christian 2014-08-11 20:12:16 UTC
This is the top of the Valgrind information, by the way... afterwards, the program will continue running about another 50 minutes or so until it runs out of swap space again, and then valgrind crashes with the long error message that was truncated (see previous post).


ca@puolukka ~ $ valgrind --tool=memcheck --leak-check=full --error-limit=no digikam
==32147== Memcheck, a memory error detector
==32147== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==32147== Using Valgrind-3.9.0 and LibVEX; rerun with -h for copyright info
==32147== Command: digikam
==32147== 
Object::connect: No such signal org::freedesktop::UPower::DeviceAdded(QString)
Object::connect: No such signal org::freedesktop::UPower::DeviceRemoved(QString)
QSqlDatabasePrivate::removeDatabase: connection 'ConnectionTest' is still in use, all queries will cease to work.
==32147== Warning: set address range perms: large range [0x14e4ff040, 0x1f4e38020) (undefined)
OpenCV Error: Insufficient memory (Failed to allocate 262144 bytes) in OutOfMemoryError, file /portage_builddir/portage/media-libs/opencv-2.4.5/work/opencv-2.4.5/modules/core/src/alloc.cpp, line 52
==32147== Warning: set address range perms: large range [0x14e4ff028, 0x1f4e38038) (noaccess)


Notes on timing:
The lines up to "Qsql" all appear while the startup window is still showing.
When I start the face recognition, the progress bar slowly climbs to 11% (slow because of Valgrind). Then memory is filled up, maybe to 7GB or so (using some swap), at which point the first warning is shown. There are no "problems" yet at this point, the program continues running and after a while memory use actually goes down. Then memory use increases again up to hitting the swap limit. This causes the OpenCV error message to appear. Progress bar is still at 11%, but goes up to 13% after these OpenCV error messages. Then memory fills up again slowly up to the limit, which causes Valgrind to crash and produce the long output, which I reported in the previous post.
Comment 5 Christian 2014-08-11 20:13:33 UTC
One more line from Valgrind:
digikam(32147)/KFACE: cv::Exception: /portage_builddir/portage/media-libs/opencv-2.4.5/work/opencv-2.4.5/modules/core/src/alloc.cpp:52: error: (-4) Failed to allocate 262144 bytes in function OutOfMemoryError

This appears about one minute after the Valgrind output in comment #4, but long before the final crash.
Comment 6 Christian 2014-08-21 14:10:05 UTC
Some more information... If I delete the libkface/database/recognition.db the problem disappears. However, it can reappear later. It seems that the recognition step can corrupt the database, so the crash is caused from that point onwards. (Or some particular "faces" can get stored in the database that then cause the crash whenever the processor attempts to process them.)
The crash, once it happens, occurs every time I try to run "recognise the faces" and also if I change the names on a recognised or "guessed" face, which causes the face recognition to try to do something with the database. But as it seems to be something involving memory runaway, the crash takes a while to happen. It's still possible to use digikam for everything else while the face recognition process in the background gobbles up all the memory and swap and then eventually crashes (taking digikam with it).
Comment 7 caulier.gilles 2014-08-21 16:37:23 UTC
The crash is probably due to full memory allocation.

If crash appears when registration of face histogram in database, well yes, the commit can be incomplete and table contents can be corrupted.

The face database managed by libkface is only accessed through face recognition management. Face detection do not access to this database.

Gilles Caulier
Comment 8 Christian 2014-08-21 19:38:26 UTC
The bug is "fixed" by deleting the recognition.db in the folder .kde4/share/apps/libkface/database and then re-learning all the faces based on the existing faces. But this doesn't address the root cause. Eventually, the bug sets in again.
Comment 9 Christian 2014-08-21 19:40:35 UTC
Is there any way to test the recognition.db for whether it is "intact"? Then I could maybe find out just at which point it is corrupted again.
In any case, even with a corrupt database (if this is indeed a part of the problem), digikam should not behave the way it is doing it now. It should detect the corruption or the memory excursion and stop whatever it is doing before it gets too extreme. Maybe somehow fix the database (if the problem is in the database) or otherwise reset the face recognition if it doesn't "work" within a reasonable time?
Comment 10 caulier.gilles 2014-08-21 19:45:38 UTC
>Is there any way to test the recognition.db for whether it is "intact"? Then I >could maybe find out just at which point it is corrupted again.

Not that i know

>In any case, even with a corrupt database (if this is indeed a part of the >problem), digikam should not behave the way it is doing it now. It should >detect the corruption or the memory excursion and stop whatever it is doing >before it gets too extreme. Maybe somehow fix the database (if the problem is >in the database) or otherwise reset the face recognition if it doesn't "work" >within a reasonable time?

Typically, with my recent changes introduced with digiKam 4.1.0 and 4.2.0, i wrapped all libkface code that call OpenCV API which handle Histograms (memory allocation, calculation) with C++ exception. If something is wrong, typically, digiKam mustnot crash and stop recognition process...

Sound like i forget something or code is incomplete somewhere...

Gilles Caulier
Comment 11 caulier.gilles 2014-08-21 19:48:35 UTC
But the lead problem with Face management is memory consumption reproducible here but only with Face detection, not Face recognition. Do you confirm ?

The memory consumption (not memory leak because allocation is free when process is done) appear for each registration of face area in main digiKam database (not libkface database)...

Gilles Caulier
Comment 12 Christian 2014-08-22 03:52:52 UTC
The lead problem is with memory consumption reproducible in face recognition or learning the name for a face. Finding faces works without problem.
When the problem happens, and from that point onwards every time, the following actions lead to the runaway memory issue: Clicking on "recognise faces", or assigning/changing the name to a face. I'm not sure if clicking on "OK" to confirm the guessed name also causes this, need to investigate more. Deleting a face marker (e.g. where it was not on a face) seems to be working without problems.
Comment 13 caulier.gilles 2014-08-22 06:02:32 UTC
If face recognition memory consumption is reproducible on your computer, can you run digiKAm into valgrind and report the console trace here ?

To use valgrind, look at this page :

https://www.digikam.org/contrib

Gilles Caulier
Comment 14 Christian 2014-08-22 15:33:53 UTC
Dear Gilles! Thanks for the help.

The first error that valgrind reports is the following. I know that it spews out lots of text when it finally crashes (that's why my earlier Valgrind log only contained the end of the output). Now I'm sending the output to a file (--log-file=...) so I can report it here. Does this initial error already help in pointing down the bug? (It happens when I correct the name on a face with a "guessed" name. The name is saved in the file but after a while Digikam crashes.) Using Digikam-4.2.0.

==25264== Memcheck, a memory error detector
==25264== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==25264== Using Valgrind-3.9.0 and LibVEX; rerun with -h for copyright info
==25264== Command: digikam
==25264== Parent PID: 11781
==25264== 
==25264== Thread 5 Thread (pooled):
==25264== Conditional jump or move depends on uninitialised value(s)
==25264==    at 0x2853AC87: picReadHeader(QIODevice*, PICHeader*, bool) (pic_read.cpp:54)
==25264==    by 0x2853C170: SoftimagePICHandler::canRead(QIODevice*) (pic_io_handler.cpp:44)                                    
==25264==    by 0x2853B9D4: SoftimagePICPlugin::capabilities(QIODevice*, QByteArray const&) const (pic_io_plugin.cpp:33)        
==25264==    by 0x9AE623B: createReadHandlerHelper(QIODevice*, QByteArray const&, bool, bool) (qimagereader.cpp:393)            
==25264==    by 0x9AE772B: QImageReaderPrivate::initHandler() (qimagereader.cpp:618)                                            
==25264==    by 0x9AE8C1F: QImageReader::read(QImage*) (qimagereader.cpp:1185)                                                  
==25264==    by 0x9AE8DFE: QImageReader::read() (qimagereader.cpp:1155)                                                         
==25264==    by 0x9AE3E92: QImage::fromData(unsigned char const*, int, char const*) (qimage.cpp:5177)                           
==25264==    by 0x9AE3F4F: QImage::loadFromData(unsigned char const*, int, char const*) (qimage.cpp:5135)                       
==25264==    by 0x6D7A8EF: KExiv2Iface::KExiv2::getImagePreview(QImage&) const (qimage.h:252)                                   
==25264==    by 0x755CF02: Digikam::PreviewLoadingTask::loadImagePreview(QImage&, QString const&) (previewtask.cpp:541)         
==25264==    by 0x755DC72: Digikam::PreviewLoadingTask::execute() (previewtask.cpp:288)                                         
==25264==
Comment 15 caulier.gilles 2014-08-22 18:20:05 UTC
No, there is no information from libkface and OpenCV.

A full valgrind trace will more suitable...

Gilles Caulier
Comment 16 Christian 2014-08-22 20:30:32 UTC
Dear Gilles - Here's the full Valgrind output. This time, when the digikam used up all the swap, it somehow logged me out of KDE as well so I couldn't copy the output from the program itself, but I logged Valgrind output into a file. Here's the full contents of that. (I had posted the beginning in the Comment 14.)

What's the next step?

==25264== Memcheck, a memory error detector
==25264== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==25264== Using Valgrind-3.9.0 and LibVEX; rerun with -h for copyright info
==25264== Command: digikam
==25264== Parent PID: 11781
==25264== 
==25264== Thread 5 Thread (pooled):
==25264== Conditional jump or move depends on uninitialised value(s)
==25264==    at 0x2853AC87: picReadHeader(QIODevice*, PICHeader*, bool) (pic_read.cpp:54)
==25264==    by 0x2853C170: SoftimagePICHandler::canRead(QIODevice*) (pic_io_handler.cpp:44)
==25264==    by 0x2853B9D4: SoftimagePICPlugin::capabilities(QIODevice*, QByteArray const&) const (pic_io_plugin.cpp:33)
==25264==    by 0x9AE623B: createReadHandlerHelper(QIODevice*, QByteArray const&, bool, bool) (qimagereader.cpp:393)
==25264==    by 0x9AE772B: QImageReaderPrivate::initHandler() (qimagereader.cpp:618)
==25264==    by 0x9AE8C1F: QImageReader::read(QImage*) (qimagereader.cpp:1185)
==25264==    by 0x9AE8DFE: QImageReader::read() (qimagereader.cpp:1155)
==25264==    by 0x9AE3E92: QImage::fromData(unsigned char const*, int, char const*) (qimage.cpp:5177)
==25264==    by 0x9AE3F4F: QImage::loadFromData(unsigned char const*, int, char const*) (qimage.cpp:5135)
==25264==    by 0x6D7A8EF: KExiv2Iface::KExiv2::getImagePreview(QImage&) const (qimage.h:252)
==25264==    by 0x755CF02: Digikam::PreviewLoadingTask::loadImagePreview(QImage&, QString const&) (previewtask.cpp:541)
==25264==    by 0x755DC72: Digikam::PreviewLoadingTask::execute() (previewtask.cpp:288)
==25264== 
==25264== Warning: set address range perms: large range [0x117564040, 0x195984020) (undefined)
==25264== Warning: set address range perms: large range [0x117564028, 0x195984038) (noaccess)
--25264-- core    : 341843968/341843968  max/curr mmap'd, 3/8 unsplit/split sb unmmap'd,  331321120/301620576 max/curr,     5346371/1998737296 totalloc-blocks/bytes,     4984086 searches 8 rzB
--25264-- dinfo   : 493404160/482103296  max/curr mmap'd, 126/106 unsplit/split sb unmmap'd,  490909072/479310352 max/curr,     2350709/1775135232 totalloc-blocks/bytes,     2376135 searches 8 rzB
--25264-- client  : 10221268992/10089021440  max/curr mmap'd, 83/1366 unsplit/split sb unmmap'd,  9748533760/9748468192 max/curr,    30053578/24221816080 totalloc-blocks/bytes,    54708611 searches 24 rzB
--25264-- demangle:    65536/       0  max/curr mmap'd, 0/1 unsplit/split sb unmmap'd,       128/       0 max/curr,          12/       896 totalloc-blocks/bytes,          11 searches 8 rzB
--25264-- ttaux   : 12075008/11636736  max/curr mmap'd, 53/3 unsplit/split sb unmmap'd,  11583344/11188272 max/curr,       33696/  31879472 totalloc-blocks/bytes,       33602 searches 8 rzB
==25264== 
==25264==     Valgrind's memory management: out of memory:
==25264==        memcheck:allocate new SecMap's request for 16384 bytes failed.
==25264==        13822648320 bytes have already been allocated.
==25264==     Valgrind cannot continue.  Sorry.
==25264== 
==25264==     There are several possible reasons for this.
==25264==     - You have some kind of memory limit in place.  Look at the
==25264==       output of 'ulimit -a'.  Is there a limit on the size of
==25264==       virtual memory or address space?
==25264==     - You have run out of swap space.
==25264==     - Valgrind has a bug.  If you think this is the case or you are
==25264==     not sure, please let us know and we'll try to fix it.
==25264==     Please note that programs can take substantially more memory than
==25264==     normal when running under Valgrind tools, eg. up to twice or
==25264==     more, depending on the tool.  On a 64-bit machine, Valgrind
==25264==     should be able to make use of up 32GB memory.  On a 32-bit
==25264==     machine, Valgrind should be able to use all the memory available
==25264==     to a single process, up to 4GB if that's how you have your
==25264==     kernel configured.  Most 32-bit Linux setups allow a maximum of
==25264==     3GB per process.
==25264== 
==25264==     Whatever the reason, Valgrind cannot continue.  Sorry.
Comment 17 Christian 2014-08-22 20:33:39 UTC
By the way, the .kde4/share/apps/libkface/recognition.db has grown in size from about 60 MB to about 130 MB during the running of the digikam - I had learned about 3 or 4 faces to make it go into the memory-eating phase. So I think something is definitely wrong in the way the face recognition is done.
Comment 18 Christian 2014-08-22 20:34:10 UTC
Missed a /database/ in the path in Comment 17, sorry.
Comment 19 caulier.gilles 2014-08-23 08:20:53 UTC
Excepted the fact that valgrind report a memory allocation exception, there is no more information about the suspicious part where memory is mangled.

I get a better vision of the problem in report #323888

Which is fully relevant of Qt SQlite plugin. This one mangle memory at each commit in database.

This is exactly what i want to proof also in your report. Perhaps you don't see these information with valgrind because you miss to install sqlite, Qt, opencv, and libkface debug packages.

Look well all my valgrind traces at end of report #323888.

Gilles Caulier
Comment 20 Christian 2014-08-23 21:09:04 UTC
Dear Gilles! The valgrind trace is all I get, there is no other output from Valgrind. See Comment 14. I have all the debug packages installed.
Comment 21 Christian 2014-10-25 17:00:05 UTC
The bug is still present in 4.4.0. After using the face labeling tool for a few times, eventually it will crash. Deleting the face recognition database file restores the functionality to working order, but of course it has to relearn the faces then.
It seems the bug is in the component that the face recognition tool uses to learn from a new face when a name is changed or attached to a face.
Comment 22 caulier.gilles 2014-10-26 14:08:05 UTC
Can you get a backtrace of crash with 4.4.0 ?

Gilles Culier
Comment 23 Christian 2014-10-28 15:16:43 UTC
Dear Gilles! I can - I followed the instructions in the Digikam webpage https://www.digikam.org/?q=contrib . But I'm afraid it's not very useful. Here you are:

Program terminated with signal SIGKILL, Killed.
The program no longer exists.
(gdb) bt
No stack.
(gdb) 

This happens a short while after tagging a few faces. The way I notice the bug is, initially the face tagging appears to work and it attaches tags, this always takes a short moment. Then after a while, changing the face tags becomes very fast (almost instantaneous), and the tags are no longer saved to the files. A while later the program window just disappears.

Any other ideas I can do?
Comment 24 Christian 2014-11-02 18:26:49 UTC
Dear Gilles! I'm getting some errors on Valgrind now :-) maybe this is helpful? It hasn't crashed yet, but I'm waiting for the crash to happen soon. Will post the rest of this log if it doesn't crash Valgrind like the last time I tried...

ca@puolukka ~ $ valgrind --tool=memcheck --leak-check=full --error-limit=no digikam ==17859== Memcheck, a memory error detector ==17859== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al. ==17859== Using Valgrind-3.9.0 and LibVEX; rerun with -h for copyright info ==17859== Command: digikam ==17859==  Object::connect: No such signal org::freedesktop::UPower::DeviceAdded(QString) Object::connect: No such signal org::freedesktop::UPower::DeviceRemoved(QString) ==17859== Thread 9 Thread (pooled): ==17859== Conditional jump or move depends on uninitialised value(s) ==17859==    at 0x2860BC87: picReadHeader(QIODevice*, PICHeader*, bool) (pic_read.cpp:54) ==17859==    by 0x2860D170: SoftimagePICHandler::canRead(QIODevice*) (pic_io_handler.cpp:44) ==17859==    by 0x2860C9D4: SoftimagePICPlugin::capabilities(QIODevice*, QByteArray const&) const (pic_io_plugin.cpp:33) ==17859==    by 0x9B4D23B: createReadHandlerHelper(QIODevice*, QByteArray const&, bool, bool) (qimagereader.cpp:393) ==17859==    by 0x9B4E72B: QImageReaderPrivate::initHandler() (qimagereader.cpp:618) ==17859==    by 0x9B4FC1F: QImageReader::read(QImage*) (qimagereader.cpp:1185) ==17859==    by 0x9B4FDFE: QImageReader::read() (qimagereader.cpp:1155) ==17859==    by 0x9B4AE92: QImage::fromData(unsigned char const*, int, char const*) (qimage.cpp:5177) ==17859==    by 0x9B4AF4F: QImage::loadFromData(unsigned char const*, int, char const*) (qimage.cpp:5135) ==17859==    by 0x6D9FA14: KExiv2Iface::KExiv2::getImagePreview(QImage&) const (qimage.h:252) ==17859==    by 0x759D03F: Digikam::ThumbnailCreator::loadImagePreview(Digikam::DMetadata const&) const (thumbnailcreator.cpp:629) ==17859==    by 0x759D573: Digikam::ThumbnailCreator::createThumbnail(Digikam::ThumbnailInfo const&, QRect const&) const (thumbnailcreator.cpp:465) ==17859==  ==17859== Conditional jump or move depends on uninitialised value(s) ==17859==    at 0xFD4C45E: CSubband::Quantize(int) (Subband.cpp:132) ==17859==    by 0xFD4CDEE: CWaveletTransform::ForwardTransform(int, int) (WaveletTransform.cpp:164) ==17859==    by 0xFD46CEA: CPGFImage::WriteHeader(CPGFStream*) (PGFimage.cpp:949) ==17859==    by 0xFD47561: CPGFImage::Write(CPGFStream*, unsigned int*, bool (*)(double, bool, void*), void*) (PGFimage.cpp:1145) ==17859==    by 0x75B09B3: Digikam::PGFUtils::writePGFImageDataToStream(QImage const&, CPGFStream&, int, unsigned int&, bool) (pgfutils.cpp:303) ==17859==    by 0x75B1251: Digikam::PGFUtils::writePGFImageData(QImage const&, QByteArray&, int, bool) (pgfutils.cpp:186) ==17859==    by 0x759E38A: Digikam::ThumbnailCreator::storeInDatabase(Digikam::ThumbnailInfo const&, Digikam::ThumbnailImage const&) const (thumbnailcreator.cpp:715) ==17859==    by 0x75A0346: Digikam::ThumbnailCreator::load(QString const&, QRect const&, bool) const (thumbnailcreator.cpp:269) ==17859==    by 0x75A1111: Digikam::ThumbnailCreator::load(QString const&) const (thumbnailcreator.cpp:201) ==17859==    by 0x75AF2D6: Digikam::ThumbnailLoadingTask::execute() (thumbnailtask.cpp:172) ==17859==    by 0x7586F85: Digikam::LoadSaveThread::run() (loadsavethread.cpp:136) ==17859==    by 0x75B5C2D: Digikam::DynamicThread::DynamicThreadPriv::run() (dynamicthread.cpp:186)                              ==17859==                                                                                                                        ==17859== Conditional jump or move depends on uninitialised value(s)                                                             ==17859==    at 0xFD4C463: CSubband::Quantize(int) (Subband.cpp:134)                                                             ==17859==    by 0xFD4CDEE: CWaveletTransform::ForwardTransform(int, int) (WaveletTransform.cpp:164)                              ==17859==    by 0xFD46CEA: CPGFImage::WriteHeader(CPGFStream*) (PGFimage.cpp:949)                                                ==17859==    by 0xFD47561: CPGFImage::Write(CPGFStream*, unsigned int*, bool (*)(double, bool, void*), void*) (PGFimage.cpp:1145)                                                                                                                                ==17859==    by 0x75B09B3: Digikam::PGFUtils::writePGFImageDataToStream(QImage const&, CPGFStream&, int, unsigned int&, bool) (pgfutils.cpp:303)                                                                                                                 ==17859==    by 0x75B1251: Digikam::PGFUtils::writePGFImageData(QImage const&, QByteArray&, int, bool) (pgfutils.cpp:186)        ==17859==    by 0x759E38A: Digikam::ThumbnailCreator::storeInDatabase(Digikam::ThumbnailInfo const&, Digikam::ThumbnailImage const&) const (thumbnailcreator.cpp:715)                                                                                            ==17859==    by 0x75A0346: Digikam::ThumbnailCreator::load(QString const&, QRect const&, bool) const (thumbnailcreator.cpp:269)  ==17859==    by 0x75A1111: Digikam::ThumbnailCreator::load(QString const&) const (thumbnailcreator.cpp:201)                      ==17859==    by 0x75AF2D6: Digikam::ThumbnailLoadingTask::execute() (thumbnailtask.cpp:172)                                      ==17859==    by 0x7586F85: Digikam::LoadSaveThread::run() (loadsavethread.cpp:136)                                               ==17859==    by 0x75B5C2D: Digikam::DynamicThread::DynamicThreadPriv::run() (dynamicthread.cpp:186)                              ==17859==                                                                                                                        ==17859== Conditional jump or move depends on uninitialised value(s)                                                             ==17859==    at 0xFD44AE3: CEncoder::WriteValue(CSubband*, int) (Encoder.cpp:327)                                                ==17859==    by 0xFD44BF4: CEncoder::Partition(CSubband*, int, int, int, int) (Encoder.cpp:258)                                  ==17859==    by 0xFD4C755: CSubband::ExtractTile(CEncoder&, bool, unsigned int, unsigned int) (Subband.cpp:185)                  ==17859==    by 0xFD47024: CPGFImage::WriteLevel() (PGFimage.cpp:1029)                                                           ==17859==    by 0xFD47492: CPGFImage::WriteImage(CPGFStream*, bool (*)(double, bool, void*), void*) (PGFimage.cpp:1103)          ==17859==    by 0xFD47575: CPGFImage::Write(CPGFStream*, unsigned int*, bool (*)(double, bool, void*), void*) (PGFimage.cpp:1148)                                                                                                                                ==17859==    by 0x75B09B3: Digikam::PGFUtils::writePGFImageDataToStream(QImage const&, CPGFStream&, int, unsigned int&, bool) (pgfutils.cpp:303)                                                                                                                 ==17859==    by 0x75B1251: Digikam::PGFUtils::writePGFImageData(QImage const&, QByteArray&, int, bool) (pgfutils.cpp:186) ==17859==    by 0x759E38A: Digikam::ThumbnailCreator::storeInDatabase(Digikam::ThumbnailInfo const&, Digikam::ThumbnailImage const&) const (thumbnailcreator.cpp:715) ==17859==    by 0x75A0346: Digikam::ThumbnailCreator::load(QString const&, QRect const&, bool) const (thumbnailcreator.cpp:269) ==17859==    by 0x75A1111: Digikam::ThumbnailCreator::load(QString const&) const (thumbnailcreator.cpp:201) ==17859==    by 0x75AF2D6: Digikam::ThumbnailLoadingTask::execute() (thumbnailtask.cpp:172) ==17859==  ==17859== Conditional jump or move depends on uninitialised value(s) ==17859==    at 0xFD44AE3: CEncoder::WriteValue(CSubband*, int) (Encoder.cpp:327) ==17859==    by 0xFD44BF4: CEncoder::Partition(CSubband*, int, int, int, int) (Encoder.cpp:258) ==17859==    by 0xFD4C755: CSubband::ExtractTile(CEncoder&, bool, unsigned int, unsigned int) (Subband.cpp:185) ==17859==    by 0xFD46F64: CPGFImage::WriteLevel() (PGFimage.cpp:1032) ==17859==    by 0xFD47492: CPGFImage::WriteImage(CPGFStream*, bool (*)(double, bool, void*), void*) (PGFimage.cpp:1103) ==17859==    by 0xFD47575: CPGFImage::Write(CPGFStream*, unsigned int*, bool (*)(double, bool, void*), void*) (PGFimage.cpp:1148) ==17859==    by 0x75B09B3: Digikam::PGFUtils::writePGFImageDataToStream(QImage const&, CPGFStream&, int, unsigned int&, bool) (pgfutils.cpp:303) ==17859==    by 0x75B1251: Digikam::PGFUtils::writePGFImageData(QImage const&, QByteArray&, int, bool) (pgfutils.cpp:186) ==17859==    by 0x759E38A: Digikam::ThumbnailCreator::storeInDatabase(Digikam::ThumbnailInfo const&, Digikam::ThumbnailImage const&) const (thumbnailcreator.cpp:715) ==17859==    by 0x75A0346: Digikam::ThumbnailCreator::load(QString const&, QRect const&, bool) const (thumbnailcreator.cpp:269) ==17859==    by 0x75A1111: Digikam::ThumbnailCreator::load(QString const&) const (thumbnailcreator.cpp:201) ==17859==    by 0x75AF2D6: Digikam::ThumbnailLoadingTask::execute() (thumbnailtask.cpp:172) ==17859==  ==17859== Conditional jump or move depends on uninitialised value(s) ==17859==    at 0xFD44AE3: CEncoder::WriteValue(CSubband*, int) (Encoder.cpp:327) ==17859==    by 0xFD44BF4: CEncoder::Partition(CSubband*, int, int, int, int) (Encoder.cpp:258) ==17859==    by 0xFD4C755: CSubband::ExtractTile(CEncoder&, bool, unsigned int, unsigned int) (Subband.cpp:185) ==17859==    by 0xFD46F98: CPGFImage::WriteLevel() (PGFimage.cpp:1033) ==17859==    by 0xFD47492: CPGFImage::WriteImage(CPGFStream*, bool (*)(double, bool, void*), void*) (PGFimage.cpp:1103) ==17859==    by 0xFD47575: CPGFImage::Write(CPGFStream*, unsigned int*, bool (*)(double, bool, void*), void*) (PGFimage.cpp:1148) ==17859==    by 0x75B09B3: Digikam::PGFUtils::writePGFImageDataToStream(QImage const&, CPGFStream&, int, unsigned int&, bool) (pgfutils.cpp:303) ==17859==    by 0x75B1251: Digikam::PGFUtils::writePGFImageData(QImage const&, QByteArray&, int, bool) (pgfutils.cpp:186) ==17859==    by 0x759E38A: Digikam::ThumbnailCreator::storeInDatabase(Digikam::ThumbnailInfo const&, Digikam::ThumbnailImage const&) const (thumbnailcreator.cpp:715) ==17859==    by 0x75A0346: Digikam::ThumbnailCreator::load(QString const&, QRect const&, bool) const (thumbnailcreator.cpp:269) ==17859==    by 0x75A1111: Digikam::ThumbnailCreator::load(QString const&) const (thumbnailcreator.cpp:201) ==17859==    by 0x75AF2D6: Digikam::ThumbnailLoadingTask::execute() (thumbnailtask.cpp:172) ==17859==  ==17859== Conditional jump or move depends on uninitialised value(s) ==17859==    at 0xFD44AE3: CEncoder::WriteValue(CSubband*, int) (Encoder.cpp:327) ==17859==    by 0xFD44BF4: CEncoder::Partition(CSubband*, int, int, int, int) (Encoder.cpp:258) ==17859==    by 0xFD4C755: CSubband::ExtractTile(CEncoder&, bool, unsigned int, unsigned int) (Subband.cpp:185) ==17859==    by 0xFD46FCF: CPGFImage::WriteLevel() (PGFimage.cpp:1034) ==17859==    by 0xFD47492: CPGFImage::WriteImage(CPGFStream*, bool (*)(double, bool, void*), void*) (PGFimage.cpp:1103) ==17859==    by 0xFD47575: CPGFImage::Write(CPGFStream*, unsigned int*, bool (*)(double, bool, void*), void*) (PGFimage.cpp:1148) ==17859==    by 0x75B09B3: Digikam::PGFUtils::writePGFImageDataToStream(QImage const&, CPGFStream&, int, unsigned int&, bool) (pgfutils.cpp:303) ==17859==    by 0x75B1251: Digikam::PGFUtils::writePGFImageData(QImage const&, QByteArray&, int, bool) (pgfutils.cpp:186) ==17859==    by 0x759E38A: Digikam::ThumbnailCreator::storeInDatabase(Digikam::ThumbnailInfo const&, Digikam::ThumbnailImage const&) const (thumbnailcreator.cpp:715) ==17859==    by 0x75A0346: Digikam::ThumbnailCreator::load(QString const&, QRect const&, bool) const (thumbnailcreator.cpp:269) ==17859==    by 0x75A1111: Digikam::ThumbnailCreator::load(QString const&) const (thumbnailcreator.cpp:201) ==17859==    by 0x75AF2D6: Digikam::ThumbnailLoadingTask::execute() (thumbnailtask.cpp:172) ==17859==  ==17859== Conditional jump or move depends on uninitialised value(s) ==17859==    at 0xFD43DF4: CEncoder::CMacroBlock::DecomposeBitplane(unsigned int, unsigned int, unsigned int, unsigned int*, unsigned int*, unsigned int*, unsigned int&, unsigned int&) (Encoder.cpp:647) ==17859==    by 0xFD444D3: CEncoder::CMacroBlock::BitplaneEncode() (Encoder.cpp:513) ==17859==    by 0xFD44A64: CEncoder::EncodeBuffer(ROIBlockHeader) (Encoder.cpp:347) ==17859==    by 0xFD44AF9: CEncoder::WriteValue(CSubband*, int) (Encoder.cpp:323) ==17859==    by 0xFD44BF4: CEncoder::Partition(CSubband*, int, int, int, int) (Encoder.cpp:258) ==17859==    by 0xFD4C755: CSubband::ExtractTile(CEncoder&, bool, unsigned int, unsigned int) (Subband.cpp:185) ==17859==    by 0xFD46F64: CPGFImage::WriteLevel() (PGFimage.cpp:1032) ==17859==    by 0xFD47492: CPGFImage::WriteImage(CPGFStream*, bool (*)(double, bool, void*), void*) (PGFimage.cpp:1103) ==17859==    by 0xFD47575: CPGFImage::Write(CPGFStream*, unsigned int*, bool (*)(double, bool, void*), void*) (PGFimage.cpp:1148) ==17859==    by 0x75B09B3: Digikam::PGFUtils::writePGFImageDataToStream(QImage const&, CPGFStream&, int, unsigned int&, bool) (pgfutils.cpp:303) ==17859==    by 0x75B1251: Digikam::PGFUtils::writePGFImageData(QImage const&, QByteArray&, int, bool) (pgfutils.cpp:186) ==17859==    by 0x759E38A: Digikam::ThumbnailCreator::storeInDatabase(Digikam::ThumbnailInfo const&, Digikam::ThumbnailImage const&) const (thumbnailcreator.cpp:715) ==17859==  ==17859== Conditional jump or move depends on uninitialised value(s) ==17859==    at 0xFD43D7B: CEncoder::CMacroBlock::DecomposeBitplane(unsigned int, unsigned int, unsigned int, unsigned int*, unsigned int*, unsigned int*, unsigned int&, unsigned int&) (Encoder.cpp:662) ==17859==    by 0xFD444D3: CEncoder::CMacroBlock::BitplaneEncode() (Encoder.cpp:513) ==17859==    by 0xFD44A64: CEncoder::EncodeBuffer(ROIBlockHeader) (Encoder.cpp:347) ==17859==    by 0xFD44AF9: CEncoder::WriteValue(CSubband*, int) (Encoder.cpp:323) ==17859==    by 0xFD44BF4: CEncoder::Partition(CSubband*, int, int, int, int) (Encoder.cpp:258) ==17859==    by 0xFD4C755: CSubband::ExtractTile(CEncoder&, bool, unsigned int, unsigned int) (Subband.cpp:185) ==17859==    by 0xFD46F64: CPGFImage::WriteLevel() (PGFimage.cpp:1032) ==17859==    by 0xFD47492: CPGFImage::WriteImage(CPGFStream*, bool (*)(double, bool, void*), void*) (PGFimage.cpp:1103) ==17859==    by 0xFD47575: CPGFImage::Write(CPGFStream*, unsigned int*, bool (*)(double, bool, void*), void*) (PGFimage.cpp:1148) ==17859==    by 0x75B09B3: Digikam::PGFUtils::writePGFImageDataToStream(QImage const&, CPGFStream&, int, unsigned int&, bool) (pgfutils.cpp:303) ==17859==    by 0x75B1251: Digikam::PGFUtils::writePGFImageData(QImage const&, QByteArray&, int, bool) (pgfutils.cpp:186) ==17859==    by 0x759E38A: Digikam::ThumbnailCreator::storeInDatabase(Digikam::ThumbnailInfo const&, Digikam::ThumbnailImage const&) const (thumbnailcreator.cpp:715) ==17859==  ==17859== Conditional jump or move depends on uninitialised value(s) ==17859==    at 0xFD43E7A: CEncoder::CMacroBlock::DecomposeBitplane(unsigned int, unsigned int, unsigned int, unsigned int*, unsigned int*, unsigned int*, unsigned int&, unsigned int&) (Encoder.cpp:702) ==17859==    by 0xFD444D3: CEncoder::CMacroBlock::BitplaneEncode() (Encoder.cpp:513) ==17859==    by 0xFD44A64: CEncoder::EncodeBuffer(ROIBlockHeader) (Encoder.cpp:347) ==17859==    by 0xFD44AF9: CEncoder::WriteValue(CSubband*, int) (Encoder.cpp:323) ==17859==    by 0xFD44BF4: CEncoder::Partition(CSubband*, int, int, int, int) (Encoder.cpp:258) ==17859==    by 0xFD4C755: CSubband::ExtractTile(CEncoder&, bool, unsigned int, unsigned int) (Subband.cpp:185) ==17859==    by 0xFD46F64: CPGFImage::WriteLevel() (PGFimage.cpp:1032) ==17859==    by 0xFD47492: CPGFImage::WriteImage(CPGFStream*, bool (*)(double, bool, void*), void*) (PGFimage.cpp:1103) ==17859==    by 0xFD47575: CPGFImage::Write(CPGFStream*, unsigned int*, bool (*)(double, bool, void*), void*) (PGFimage.cpp:1148) ==17859==    by 0x75B09B3: Digikam::PGFUtils::writePGFImageDataToStream(QImage const&, CPGFStream&, int, unsigned int&, bool) (pgfutils.cpp:303) ==17859==    by 0x75B1251: Digikam::PGFUtils::writePGFImageData(QImage const&, QByteArray&, int, bool) (pgfutils.cpp:186) ==17859==    by 0x759E38A: Digikam::ThumbnailCreator::storeInDatabase(Digikam::ThumbnailInfo const&, Digikam::ThumbnailImage const&) const (thumbnailcreator.cpp:715) ==17859==  ==17859== Conditional jump or move depends on uninitialised value(s) ==17859==    at 0x9A83450: qt_blend_argb32_on_argb32_ssse3(unsigned char*, int, unsigned char const*, int, int, int, int) (qdrawhelper_ssse3.cpp:52) ==17859==    by 0x9C50F4B: QRasterPaintEngine::drawImage(QPointF const&, QImage const&) (qpaintengine_raster.cpp:2182) ==17859==    by 0x9BDDB4D: QPainter::drawImage(QPointF const&, QImage const&) (qpainter.cpp:5636) ==17859==    by 0x759CC5E: Digikam::ThumbnailCreator::handleAlphaChannel(QImage const&) const (qpainter.h:935) ==17859==    by 0x75A0432: Digikam::ThumbnailCreator::load(QString const&, QRect const&, bool) const (thumbnailcreator.cpp:300) ==17859==    by 0x75A1111: Digikam::ThumbnailCreator::load(QString const&) const (thumbnailcreator.cpp:201) ==17859==    by 0x75AF2D6: Digikam::ThumbnailLoadingTask::execute() (thumbnailtask.cpp:172) ==17859==    by 0x7586F85: Digikam::LoadSaveThread::run() (loadsavethread.cpp:136) ==17859==    by 0x75B5C2D: Digikam::DynamicThread::DynamicThreadPriv::run() (dynamicthread.cpp:186) ==17859==    by 0xAAC2DBA: QThreadPoolThread::run() (qthreadpool.cpp:107) ==17859==    by 0xAACF2DB: QThreadPrivate::start(void*) (qthread_unix.cpp:338) ==17859==    by 0xDB512D9: start_thread (pthread_create.c:309) ==17859==  ==17859== Thread 11 Thread (pooled): ==17859== Conditional jump or move depends on uninitialised value(s) ==17859==    at 0xFD44AE3: CEncoder::WriteValue(CSubband*, int) (Encoder.cpp:327) ==17859==    by 0xFD44CF4: CEncoder::Partition(CSubband*, int, int, int, int) (Encoder.cpp:283) ==17859==    by 0xFD4C755: CSubband::ExtractTile(CEncoder&, bool, unsigned int, unsigned int) (Subband.cpp:185) ==17859==    by 0xFD47024: CPGFImage::WriteLevel() (PGFimage.cpp:1029) ==17859==    by 0xFD47492: CPGFImage::WriteImage(CPGFStream*, bool (*)(double, bool, void*), void*) (PGFimage.cpp:1103) ==17859==    by 0xFD47575: CPGFImage::Write(CPGFStream*, unsigned int*, bool (*)(double, bool, void*), void*) (PGFimage.cpp:1148) ==17859==    by 0x75B09B3: Digikam::PGFUtils::writePGFImageDataToStream(QImage const&, CPGFStream&, int, unsigned int&, bool) (pgfutils.cpp:303) ==17859==    by 0x75B1251: Digikam::PGFUtils::writePGFImageData(QImage const&, QByteArray&, int, bool) (pgfutils.cpp:186) ==17859==    by 0x759E38A: Digikam::ThumbnailCreator::storeInDatabase(Digikam::ThumbnailInfo const&, Digikam::ThumbnailImage const&) const (thumbnailcreator.cpp:715) ==17859==    by 0x75A0346: Digikam::ThumbnailCreator::load(QString const&, QRect const&, bool) const (thumbnailcreator.cpp:269) ==17859==    by 0x75A1111: Digikam::ThumbnailCreator::load(QString const&) const (thumbnailcreator.cpp:201) ==17859==    by 0x75AF2D6: Digikam::ThumbnailLoadingTask::execute() (thumbnailtask.cpp:172) ==17859==  ==17859== Conditional jump or move depends on uninitialised value(s) ==17859==    at 0xFD44AE3: CEncoder::WriteValue(CSubband*, int) (Encoder.cpp:327) ==17859==    by 0xFD44CF4: CEncoder::Partition(CSubband*, int, int, int, int) (Encoder.cpp:283) ==17859==    by 0xFD4C755: CSubband::ExtractTile(CEncoder&, bool, unsigned int, unsigned int) (Subband.cpp:185) ==17859==    by 0xFD46F64: CPGFImage::WriteLevel() (PGFimage.cpp:1032) ==17859==    by 0xFD47492: CPGFImage::WriteImage(CPGFStream*, bool (*)(double, bool, void*), void*) (PGFimage.cpp:1103) ==17859==    by 0xFD47575: CPGFImage::Write(CPGFStream*, unsigned int*, bool (*)(double, bool, void*), void*) (PGFimage.cpp:1148) ==17859==    by 0x75B09B3: Digikam::PGFUtils::writePGFImageDataToStream(QImage const&, CPGFStream&, int, unsigned int&, bool) (pgfutils.cpp:303) ==17859==    by 0x75B1251: Digikam::PGFUtils::writePGFImageData(QImage const&, QByteArray&, int, bool) (pgfutils.cpp:186) ==17859==    by 0x759E38A: Digikam::ThumbnailCreator::storeInDatabase(Digikam::ThumbnailInfo const&, Digikam::ThumbnailImage const&) const (thumbnailcreator.cpp:715) ==17859==    by 0x75A0346: Digikam::ThumbnailCreator::load(QString const&, QRect const&, bool) const (thumbnailcreator.cpp:269) ==17859==    by 0x75A1111: Digikam::ThumbnailCreator::load(QString const&) const (thumbnailcreator.cpp:201) ==17859==    by 0x75AF2D6: Digikam::ThumbnailLoadingTask::execute() (thumbnailtask.cpp:172) ==17859==  ==17859== Conditional jump or move depends on uninitialised value(s) ==17859==    at 0xFD44AE3: CEncoder::WriteValue(CSubband*, int) (Encoder.cpp:327) ==17859==    by 0xFD44CF4: CEncoder::Partition(CSubband*, int, int, int, int) (Encoder.cpp:283) ==17859==    by 0xFD4C755: CSubband::ExtractTile(CEncoder&, bool, unsigned int, unsigned int) (Subband.cpp:185) ==17859==    by 0xFD46F98: CPGFImage::WriteLevel() (PGFimage.cpp:1033) ==17859==    by 0xFD47492: CPGFImage::WriteImage(CPGFStream*, bool (*)(double, bool, void*), void*) (PGFimage.cpp:1103) ==17859==    by 0xFD47575: CPGFImage::Write(CPGFStream*, unsigned int*, bool (*)(double, bool, void*), void*) (PGFimage.cpp:1148) ==17859==    by 0x75B09B3: Digikam::PGFUtils::writePGFImageDataToStream(QImage const&, CPGFStream&, int, unsigned int&, bool) (pgfutils.cpp:303) ==17859==    by 0x75B1251: Digikam::PGFUtils::writePGFImageData(QImage const&, QByteArray&, int, bool) (pgfutils.cpp:186) ==17859==    by 0x759E38A: Digikam::ThumbnailCreator::storeInDatabase(Digikam::ThumbnailInfo const&, Digikam::ThumbnailImage const&) const (thumbnailcreator.cpp:715) ==17859==    by 0x75A0346: Digikam::ThumbnailCreator::load(QString const&, QRect const&, bool) const (thumbnailcreator.cpp:269) ==17859==    by 0x75A1111: Digikam::ThumbnailCreator::load(QString const&) const (thumbnailcreator.cpp:201) ==17859==    by 0x75AF2D6: Digikam::ThumbnailLoadingTask::execute() (thumbnailtask.cpp:172) ==17859==  ==17859== Conditional jump or move depends on uninitialised value(s) ==17859==    at 0xFD44AE3: CEncoder::WriteValue(CSubband*, int) (Encoder.cpp:327) ==17859==    by 0xFD44CF4: CEncoder::Partition(CSubband*, int, int, int, int) (Encoder.cpp:283) ==17859==    by 0xFD4C755: CSubband::ExtractTile(CEncoder&, bool, unsigned int, unsigned int) (Subband.cpp:185) ==17859==    by 0xFD46FCF: CPGFImage::WriteLevel() (PGFimage.cpp:1034) ==17859==    by 0xFD47492: CPGFImage::WriteImage(CPGFStream*, bool (*)(double, bool, void*), void*) (PGFimage.cpp:1103) ==17859==    by 0xFD47575: CPGFImage::Write(CPGFStream*, unsigned int*, bool (*)(double, bool, void*), void*) (PGFimage.cpp:1148) ==17859==    by 0x75B09B3: Digikam::PGFUtils::writePGFImageDataToStream(QImage const&, CPGFStream&, int, unsigned int&, bool) (pgfutils.cpp:303) ==17859==    by 0x75B1251: Digikam::PGFUtils::writePGFImageData(QImage const&, QByteArray&, int, bool) (pgfutils.cpp:186) ==17859==    by 0x759E38A: Digikam::ThumbnailCreator::storeInDatabase(Digikam::ThumbnailInfo const&, Digikam::ThumbnailImage const&) const (thumbnailcreator.cpp:715) ==17859==    by 0x75A0346: Digikam::ThumbnailCreator::load(QString const&, QRect const&, bool) const (thumbnailcreator.cpp:269) ==17859==    by 0x75A1111: Digikam::ThumbnailCreator::load(QString const&) const (thumbnailcreator.cpp:201) ==17859==    by 0x75AF2D6: Digikam::ThumbnailLoadingTask::execute() (thumbnailtask.cpp:172) ==17859==  digikam(17859)/digikam (core) Digikam::ThumbnailCreator::createThumbnail: Cannot create thumbnail for  "/home/ca/path/to/filename.JPG"  digikam(17859)/digikam (core) Digikam::ThumbnailCreator::load: Thumbnail is null for  "/home/ca/path/to/samefilename.JPG"
Comment 25 Christian 2014-11-02 18:32:35 UTC
Oops what a messy paste. Is there any way I can paste the valgrind output without making a mess? I took it from the console window with "select all", "copy". Even copying to e.g. Kate to make a text file, it is all on one line and messy. Sorry about that.
Comment 26 Christian 2014-11-03 04:39:37 UTC
Created attachment 89414 [details]
valgrind output (end of it)

The end of the Valgrind output is below. There's a piece missing in the middle because the console buffer was too small. I think the previous post is more helpful for debugging. (And for some reason, this copy-paste looks ok in Kate, so I'm attaching it as txt.)
Comment 27 Christian 2014-11-06 05:49:49 UTC
Created attachment 89469 [details]
Another valgrind output

Maybe the lines at the end are useful?
==4837== Warning: set address range perms: large range [0x175191028, 0x231f97038) (noaccess)
digikam(4837)/KFACE: cv::Exception training LBPH: /portage_builddir/portage/media-libs/opencv-2.4.9/work/opencv-2.4.9/modules/core/src/alloc.cpp:52: error: (-4) Failed to allocate 262144 bytes in function OutOfMemoryError
Comment 28 caulier.gilles 2014-12-15 12:51:50 UTC
Git commit f6bcec9d07f0f6530835498370a6042f9b1e1675 by Marcel Wiesweg.
Committed on 14/11/2014 at 09:56.
Pushed by mwiesweg into branch 'master'.

Some fixes in face progress calculation

M  +1    -0    utilities/facemanagement/facepipeline.cpp
M  +2    -0    utilities/facemanagement/facepipeline.h
M  +31   -14   utilities/maintenance/facedetector.cpp

http://commits.kde.org/digikam/f6bcec9d07f0f6530835498370a6042f9b1e1675

diff --git a/utilities/facemanagement/facepipeline.cpp b/utilities/facemanagement/facepipeline.cpp
index a655385..d512a92 100644
--- a/utilities/facemanagement/facepipeline.cpp
+++ b/utilities/facemanagement/facepipeline.cpp
@@ -1171,6 +1171,7 @@ void FacePipeline::Private::send(FacePipelineExtendedPackage::Ptr package)
 {
     start();
     ++totalPackagesAdded;
+    emit(q->processing(*package));

     if (senderFlowControl(package))
     {
diff --git a/utilities/facemanagement/facepipeline.h b/utilities/facemanagement/facepipeline.h
index 4b381ca..45e733a 100644
--- a/utilities/facemanagement/facepipeline.h
+++ b/utilities/facemanagement/facepipeline.h
@@ -292,6 +292,8 @@ Q_SIGNALS:
     /// Emitted when processing has started
     void started(const QString& message);

+    /// Emitted when one package begins processing
+    void processing(const FacePipelinePackage& package);
     /// Emitted when one package has finished processing
     void processed(const FacePipelinePackage& package);
     void progressValueChanged(float progress);
diff --git a/utilities/maintenance/facedetector.cpp b/utilities/maintenance/facedetector.cpp
index 7bd8c0e..222652b 100644
--- a/utilities/maintenance/facedetector.cpp
+++ b/utilities/maintenance/facedetector.cpp
@@ -96,18 +96,27 @@ class FaceDetector::Private
 public:

     Private()
+        : benchmark(false),
+          total(0),
+          progressValue(0),
+          currentProgressChunk(0),
+          currentScheduled(0),
+          currentFinished(0)
     {
-        benchmark  = false;
-        total      = 0;
     }

-    bool               benchmark;
+    bool                benchmark;

-    int                total;
+    int                 total;

-    AlbumPointerList<> albumTodoList;
-    ImageInfoJob       albumListing;
-    FacePipeline       pipeline;
+    AlbumPointerList<>  albumTodoList;
+    ImageInfoJob        albumListing;
+    FacePipeline        pipeline;
+    QMap<Album*,double> relativeProgressValue;
+    double              progressValue;
+    double              currentProgressChunk;
+    int                 currentScheduled;
+    int                 currentFinished;
 };

 FaceDetector::FaceDetector(const FaceScanSettings& settings, ProgressItem* const parent)
@@ -275,25 +284,33 @@ void FaceDetector::slotStart()
         QApplication::restoreOverrideCursor();
     }

-    d->total = 0;
-
+    // first, we use the relativeProgressValue map to store absolute counts
     foreach(Album* const album, d->albumTodoList)
     {
         if (album->type() == Album::PHYSICAL)
         {
-            d->total += palbumCounts.value(album->id());
+            d->relativeProgressValue[album] = palbumCounts.value(album->id());
         }
         else
             // this is possibly broken of course because we do not know if images have multiple tags,
             // but there's no better solution without expensive operation
         {
-            d->total += talbumCounts.value(album->id());
+            d->relativeProgressValue[album] = talbumCounts.value(album->id());
         }
     }
-
-    kDebug() << "Total is" << d->total;
-
+    // second, calculate (approximate) overall sum
+    d->total = 0;
+    foreach (double count, d->relativeProgressValue)
+    {
+        d->total += (int)count;
+    }
     d->total = qMax(1, d->total);
+    kDebug() << "Total is" << d->total;
+    // third, break absolute to relative values
+    for (QMap<Album*,double>::iterator it = d->relativeProgressValue.begin(); it != d->relativeProgressValue.end(); ++it)
+    {
+        it.value() /= double(d->total);
+    }

     setUsesBusyIndicator(false);
     setTotalItems(d->total);
Comment 29 caulier.gilles 2014-12-15 12:54:27 UTC
Git commit 59f0bdb6b2709171354418ed297d4aa1d667ebad by Marcel Wiesweg.
Committed on 15/11/2014 at 13:47.
Pushed by mwiesweg into branch 'master'.

Add database cleanup calls to have a clean shutdown of SQLite data at application termination

M  +3    -0    app/main/main.cpp
M  +17   -3    tests/testdatabase.cpp

http://commits.kde.org/digikam/59f0bdb6b2709171354418ed297d4aa1d667ebad

diff --git a/app/main/main.cpp b/app/main/main.cpp
index 3564d23..85fcbc7 100644
--- a/app/main/main.cpp
+++ b/app/main/main.cpp
@@ -62,6 +62,7 @@
 #include "databaseparameters.h"
 #include "digikamapp.h"
 #include "scancontroller.h"
+#include "thumbnaildatabaseaccess.h"
 #include "version.h"

 using namespace Digikam;
@@ -235,6 +236,8 @@ int main(int argc, char* argv[])

     int ret = app.exec();

+    DatabaseAccess::cleanUpDatabase();
+    ThumbnailDatabaseAccess::cleanUpDatabase();
     KExiv2Iface::KExiv2::cleanupExiv2();

     return ret;
diff --git a/tests/testdatabase.cpp b/tests/testdatabase.cpp
index 10c14ad..0930029 100644
--- a/tests/testdatabase.cpp
+++ b/tests/testdatabase.cpp
@@ -30,6 +30,7 @@
 #include <QSqlDatabase>
 #include <QDBusConnection>
 #include <QString>
+#include <QTimer>

 // KDE includes

@@ -47,6 +48,7 @@
 #include "databaseparameters.h"
 #include "scancontroller.h"
 #include "setup.h"
+#include "thumbnaildatabaseaccess.h"
 #include "version.h"

 namespace Digikam
@@ -76,16 +78,28 @@ int main(int argc, char** argv)
     KCmdLineArgs::init(argc, argv, &aboutData);
     KApplication app;

-    DatabaseParameters params = DatabaseParameters::parametersFromConfig(KGlobal::config());
+    DatabaseParameters params;
+    params.databaseType = DatabaseParameters::SQLiteDatabaseType();
+    params.setDatabasePath(QDir::currentPath() + "/digikam-test.db");
+    params.setThumbsDatabasePath(QDir::currentPath() + "/digikam-thumbs-test.db");
+
     params.legacyAndDefaultChecks();

     QDBusConnection::sessionBus().registerService("org.kde.digikam.startup-" +
                      QString::number(QCoreApplication::instance()->applicationPid()));

     // initialize database
-    bool b = AlbumManager::instance()->setDatabase(params, false);
+    bool b = AlbumManager::instance()->setDatabase(params, false, "/media/fotos/Digikam Sample/");

     kDebug() << "Database initialization done: " << b;
-
+
+    QTimer::singleShot(500, &app, SLOT(quit()));
+    app.exec();
+
+    ScanController::instance()->shutDown();
+
+    DatabaseAccess::cleanUpDatabase();
+    ThumbnailDatabaseAccess::cleanUpDatabase();
+
     return 0;
 }
Comment 30 caulier.gilles 2014-12-15 12:55:12 UTC
Git commit b9f8dbfe470609ef31c5442cb2a4c97e02344233 by Marcel Wiesweg.
Committed on 15/11/2014 at 13:45.
Pushed by mwiesweg into branch 'master'.

Rewrite per-thread database connection cleanup
Use QThreadStorage of a per-thread DatabaseThreadData object which is destroyed when the thread finishes.

M  +103  -113  libs/database/core/databasecorebackend.cpp
M  +0    -5    libs/database/core/databasecorebackend.h
M  +22   -12   libs/database/core/databasecorebackend_p.h

http://commits.kde.org/digikam/b9f8dbfe470609ef31c5442cb2a4c97e02344233

diff --git a/libs/database/core/databasecorebackend.cpp b/libs/database/core/databasecorebackend.cpp
index c553bb1..76a958a 100644
--- a/libs/database/core/databasecorebackend.cpp
+++ b/libs/database/core/databasecorebackend.cpp
@@ -79,22 +79,64 @@ public:
     }
 };

+DatabaseThreadData::DatabaseThreadData()
+    : valid(0),
+      transactionCount(0)
+{
+}
+
+DatabaseThreadData::~DatabaseThreadData()
+{
+    if (transactionCount)
+    {
+        kDebug() << "WARNING !!! Transaction count is" << transactionCount << "when destroying database!!!";
+    }
+    closeDatabase();
+}
+
+void DatabaseThreadData::closeDatabase()
+{
+    QString connectionToRemove;
+    if (database.isOpen())
+    {
+        connectionToRemove = database.connectionName();
+    }
+
+    // Destroy object
+    database = QSqlDatabase();
+
+    valid            = 0;
+    transactionCount = 0;
+    lastError        = QSqlError();
+
+    // Remove connection
+    if (!connectionToRemove.isNull())
+    {
+        QSqlDatabase::removeDatabase(connectionToRemove);
+    }
+}
+
 DatabaseCoreBackendPrivate::DatabaseCoreBackendPrivate(DatabaseCoreBackend* const backend)
-    : q(backend)
+    : currentValidity(0),
+      isInTransaction(false),
+      status(DatabaseCoreBackend::Unavailable),
+      lock(0),
+      operationStatus(DatabaseCoreBackend::ExecuteNormal),
+      errorLockOperationStatus(DatabaseCoreBackend::ExecuteNormal),
+      errorHandler(0),
+      q(backend)
 {
-    status                   = DatabaseCoreBackend::Unavailable;
-    isInTransaction          = false;
-    operationStatus          = DatabaseCoreBackend::ExecuteNormal;
-    errorHandler             = 0;
-    lock                     = 0;
-    errorLockOperationStatus = DatabaseCoreBackend::ExecuteNormal;
 }

-void DatabaseCoreBackendPrivate::init(const QString& name, DatabaseLocking* const l)
+DatabaseCoreBackendPrivate::~DatabaseCoreBackendPrivate()
 {
-    QObject::connect(QCoreApplication::instance(), SIGNAL(aboutToQuit()),
-                     q, SLOT(slotMainThreadFinished()));
+    // Must be shut down from the main thread.
+    // Clean up the QThreadStorage. It deletes any stored data.
+    threadDataStorage.setLocalData(0);
+}

+void DatabaseCoreBackendPrivate::init(const QString& name, DatabaseLocking* const l)
+{
     backendName = name;
     lock        = l;

@@ -110,82 +152,43 @@ void DatabaseCoreBackendPrivate::init(const QString& name, DatabaseLocking* cons
 // finishing of the thread.
 QSqlDatabase DatabaseCoreBackendPrivate::databaseForThread()
 {
-    QThread* const thread = QThread::currentThread();
-    QSqlDatabase db       = threadDatabases[thread];
-    int isValid           = databasesValid[thread];
-
-    if (!isValid || !db.isOpen())
+    DatabaseThreadData* threadData = 0;
+    if (!threadDataStorage.hasLocalData())
     {
-        // need to open a db for thread
-        bool success = open(db);
-
-        if (!success)
-        {
-            kDebug() << "Error while opening the database. Details: [" << db.lastError() << "]";
-        }
-
-        QObject::connect(thread, SIGNAL(finished()),
-                         q, SLOT(slotThreadFinished()));
+        threadData = new DatabaseThreadData;
+        threadDataStorage.setLocalData(threadData);
     }
-
-#ifdef DATABASCOREBACKEND_DEBUG
     else
     {
-        kDebug() << "Database ["<< connectionName(thread) <<"] already open for thread ["<< thread <<"].";
+        threadData = threadDataStorage.localData();
     }

-#endif
-
-    return db;
-}
-
-void DatabaseCoreBackendPrivate::closeDatabaseForThread()
-{
-    QThread* const thread = QThread::currentThread();
+    // do we need to reopen the database because parameter changed and validity was increased?
+    if (threadData->valid && threadData->valid < currentValidity)
+    {
+        threadData->closeDatabase();
+    }

-    // scope, so that db is destructed when calling removeDatabase
+    if (!threadData->valid || !threadData->database.isOpen())
     {
-        QSqlDatabase db = threadDatabases[thread];
+        threadData->database = createDatabaseConnection();

-        if (db.isValid())
+        if (threadData->database.open())
+        {
+            threadData->valid = currentValidity;
+        }
+        else
         {
-            db.close();
+            kDebug() << "Error while opening the database. Error was" << threadData->database.lastError();
         }
     }

-    threadDatabases.remove(thread);
-    databaseErrors.remove(thread);
-    databasesValid[thread] = 0;
-    transactionCount.remove(thread);
-    QSqlDatabase::removeDatabase(connectionName(thread));
-}
-
-QSqlError DatabaseCoreBackendPrivate::databaseErrorForThread()
-{
-    QThread* const thread = QThread::currentThread();
-    return databaseErrors[thread];
-}
-
-void DatabaseCoreBackendPrivate::setDatabaseErrorForThread(const QSqlError& lastError)
-{
-    QThread* const thread = QThread::currentThread();
-    databaseErrors.insert(thread, lastError);
-}
-
-QString DatabaseCoreBackendPrivate::connectionName(QThread* const thread)
-{
-    return backendName + QString::number((quintptr)thread);
+    return threadData->database;
 }

-bool DatabaseCoreBackendPrivate::open(QSqlDatabase& db)
+QSqlDatabase DatabaseCoreBackendPrivate::createDatabaseConnection()
 {
-    if (db.isValid())
-    {
-        db.close();
-    }
-
-    QThread* const thread  = QThread::currentThread();
-    db                     = QSqlDatabase::addDatabase(parameters.databaseType, connectionName(thread));
+    QSqlDatabase db        = QSqlDatabase::addDatabase(parameters.databaseType, connectionName());
     QString connectOptions = parameters.connectOptions;

     if (parameters.isSQLite())
@@ -211,46 +214,47 @@ bool DatabaseCoreBackendPrivate::open(QSqlDatabase& db)
     db.setUserName(parameters.userName);
     db.setPassword(parameters.password);

-    bool success = db.open();
+    return db;
+}

-    if (success==false)
+void DatabaseCoreBackendPrivate::closeDatabaseForThread()
+{
+    if (threadDataStorage.hasLocalData())
     {
-        kDebug() << "Error while opening the database. Error was <" << db.lastError() << ">";
+        threadDataStorage.localData()->closeDatabase();
     }
-
-    threadDatabases[thread]  = db;
-    databasesValid[thread]   = 1;
-    transactionCount[thread] = 0;
-
-    return success;
 }

-bool DatabaseCoreBackendPrivate::incrementTransactionCount()
+QSqlError DatabaseCoreBackendPrivate::databaseErrorForThread()
 {
-    QThread* const thread = QThread::currentThread();
-    return (!transactionCount[thread]++);
+    if (threadDataStorage.hasLocalData())
+    {
+        return threadDataStorage.localData()->lastError;
+    }
+    return QSqlError();
 }

-bool DatabaseCoreBackendPrivate::decrementTransactionCount()
+void DatabaseCoreBackendPrivate::setDatabaseErrorForThread(const QSqlError& lastError)
 {
-    QThread* const thread = QThread::currentThread();
-    return (!--transactionCount[thread]);
+    if (threadDataStorage.hasLocalData())
+    {
+        threadDataStorage.localData()->lastError = lastError;
+    }
 }

-bool DatabaseCoreBackendPrivate::isInTransactionInOtherThread() const
+QString DatabaseCoreBackendPrivate::connectionName()
 {
-    QThread* const thread = QThread::currentThread();
-    QHash<QThread*, int>::const_iterator it;
+    return backendName + QString::number((quintptr)QThread::currentThread());
+}

-    for (it = transactionCount.constBegin(); it != transactionCount.constEnd(); ++it)
-    {
-        if (it.key() != thread && it.value())
-        {
-            return true;
-        }
-    }
+bool DatabaseCoreBackendPrivate::incrementTransactionCount()
+{
+    return (!threadDataStorage.localData()->transactionCount++);
+}

-    return false;
+bool DatabaseCoreBackendPrivate::decrementTransactionCount()
+{
+    return (!--threadDataStorage.localData()->transactionCount);
 }

 bool DatabaseCoreBackendPrivate::isInMainThread() const
@@ -740,18 +744,6 @@ void DatabaseCoreBackend::setDatabaseErrorHandler(DatabaseErrorHandler* const ha
     d->errorHandler = handler;
 }

-void DatabaseCoreBackend::slotThreadFinished()
-{
-    Q_D(DatabaseCoreBackend);
-    d->closeDatabaseForThread();
-}
-
-void DatabaseCoreBackend::slotMainThreadFinished()
-{
-    Q_D(DatabaseCoreBackend);
-    d->closeDatabaseForThread();
-}
-
 bool DatabaseCoreBackend::isCompatible(const DatabaseParameters& parameters)
 {
     return QSqlDatabase::drivers().contains(parameters.databaseType);
@@ -761,10 +753,8 @@ bool DatabaseCoreBackend::open(const DatabaseParameters& parameters)
 {
     Q_D(DatabaseCoreBackend);
     d->parameters = parameters;
-
-    // Force possibly opened thread dbs to re-open with new parameters.
-    // They are not accessible from this thread!
-    d->databasesValid.clear();
+    // This will make possibly opened thread dbs reload at next access
+    d->currentValidity++;

     int retries = 0;

@@ -1634,7 +1624,7 @@ DatabaseCoreBackend::QueryState DatabaseCoreBackend::commitTransaction()
 bool DatabaseCoreBackend::isInTransaction() const
 {
     Q_D(const DatabaseCoreBackend);
-    return d->isInTransactionInOtherThread();
+    return d->isInTransaction;
 }

 void DatabaseCoreBackend::rollbackTransaction()
diff --git a/libs/database/core/databasecorebackend.h b/libs/database/core/databasecorebackend.h
index 41e47da..fa4dba4 100644
--- a/libs/database/core/databasecorebackend.h
+++ b/libs/database/core/databasecorebackend.h
@@ -472,11 +472,6 @@ public:
             LastInsertId
     */

-private Q_SLOTS:
-
-    void slotThreadFinished();
-    void slotMainThreadFinished();
-
 protected:

     DatabaseCoreBackendPrivate* const d_ptr;
diff --git a/libs/database/core/databasecorebackend_p.h b/libs/database/core/databasecorebackend_p.h
index 2078509..ff3a3fa 100644
--- a/libs/database/core/databasecorebackend_p.h
+++ b/libs/database/core/databasecorebackend_p.h
@@ -29,6 +29,7 @@
 #include <QHash>
 #include <QSqlDatabase>
 #include <QThread>
+#include <QThreadStorage>
 #include <QWaitCondition>

 // Local includes
@@ -40,25 +41,38 @@
 namespace Digikam
 {

+class DatabaseThreadData
+{
+public:
+
+    DatabaseThreadData();
+    ~DatabaseThreadData();
+
+    void closeDatabase();
+
+    QSqlDatabase database;
+    int          valid;
+    int          transactionCount;
+    QSqlError    lastError;
+};
+
 class DIGIKAM_EXPORT DatabaseCoreBackendPrivate : public DatabaseErrorAnswer
 {
 public:

     explicit DatabaseCoreBackendPrivate(DatabaseCoreBackend* const backend);
-    virtual ~DatabaseCoreBackendPrivate()
-    {
-    }
+    virtual ~DatabaseCoreBackendPrivate();

     void init(const QString& connectionName, DatabaseLocking* const locking);

-    QString connectionName(QThread* const thread);
+    QString connectionName();

     QSqlDatabase databaseForThread();
     QSqlError    databaseErrorForThread();
     void         setDatabaseErrorForThread(const QSqlError& lastError);

+    QSqlDatabase createDatabaseConnection();
     void closeDatabaseForThread();
-    bool open(QSqlDatabase& db);
     bool incrementTransactionCount();
     bool decrementTransactionCount();
     bool isInTransactionInOtherThread() const;
@@ -88,14 +102,10 @@ public:

 public:

-    // this is always accessed in mutex context, no need for QThreadStorage
-    QHash<QThread*, QSqlDatabase>             threadDatabases;
-    // this is not only db.isValid(), but also "parameters changed, need to reopen"
-    QHash<QThread*, int>                      databasesValid;
-    // for recursive transactions
-    QHash<QThread*, int>                      transactionCount;
+    QThreadStorage<DatabaseThreadData*>       threadDataStorage;

-    QHash<QThread*, QSqlError>                databaseErrors;
+    // This compares to DatabaseThreadData's valid. If currentValidity is increased and > valid, the db is marked as invalid
+    int                                       currentValidity;

     bool                                      isInTransaction;
Comment 31 caulier.gilles 2014-12-15 12:56:57 UTC
Git commit bab8c3f159930a3b0b31d09b25b9eb42ab1c3c62 by Marcel Wiesweg.
Committed on 15/11/2014 at 14:45.
Pushed by mwiesweg into branch 'master'.

Backport all core db changes regarding thread clean up from main digikam
Back and forward port code polish and style changes

M  +153  -150  libkface/database/databasecorebackend.cpp
M  +15   -12   libkface/database/databasecorebackend.h
M  +35   -25   libkface/database/databasecorebackend_p.h
M  +1    -0    libkface/database/databaseparameters.h

http://commits.kde.org/libkface/bab8c3f159930a3b0b31d09b25b9eb42ab1c3c62

diff --git a/libkface/database/databasecorebackend.cpp b/libkface/database/databasecorebackend.cpp
index 784e9b7..2193ce2 100644
--- a/libkface/database/databasecorebackend.cpp
+++ b/libkface/database/databasecorebackend.cpp
@@ -21,12 +21,6 @@
  *
  * ============================================================ */

-/*
-#ifndef DATABASCOREBACKEND_DEBUG
-#define DATABASCOREBACKEND_DEBUG
-#endif
-*/
-
 #include "databasecorebackend.moc"
 #include "databasecorebackend_p.h"

@@ -51,8 +45,8 @@

 // Local includes

-#include "schemaupdater.h"
 #include "dbactiontype.h"
+#include "schemaupdater.h"

 namespace KFaceIface
 {
@@ -102,22 +96,65 @@ DatabaseCoreBackendPrivate::ErrorLocker::ErrorLocker(DatabaseCoreBackendPrivate*

 // -----------------------------------------------------------------------------------------

+
+DatabaseThreadData::DatabaseThreadData()
+    : valid(0),
+      transactionCount(0)
+{
+}
+
+DatabaseThreadData::~DatabaseThreadData()
+{
+    if (transactionCount)
+    {
+        kDebug() << "WARNING !!! Transaction count is" << transactionCount << "when destroying database!!!";
+    }
+    closeDatabase();
+}
+
+void DatabaseThreadData::closeDatabase()
+{
+    QString connectionToRemove;
+    if (database.isOpen())
+    {
+        connectionToRemove = database.connectionName();
+    }
+
+    // Destroy object
+    database = QSqlDatabase();
+
+    valid            = 0;
+    transactionCount = 0;
+    lastError        = QSqlError();
+
+    // Remove connection
+    if (!connectionToRemove.isNull())
+    {
+        QSqlDatabase::removeDatabase(connectionToRemove);
+    }
+}
+
 DatabaseCoreBackendPrivate::DatabaseCoreBackendPrivate(DatabaseCoreBackend* const backend)
-    : q(backend)
+    : currentValidity(0),
+      isInTransaction(false),
+      status(DatabaseCoreBackend::Unavailable),
+      lock(0),
+      operationStatus(DatabaseCoreBackend::ExecuteNormal),
+      errorLockOperationStatus(DatabaseCoreBackend::ExecuteNormal),
+      errorHandler(0),
+      q(backend)
 {
-    status                   = DatabaseCoreBackend::Unavailable;
-    isInTransaction          = false;
-    operationStatus          = DatabaseCoreBackend::ExecuteNormal;
-    errorLockOperationStatus = DatabaseCoreBackend::ExecuteNormal;
-    errorHandler             = 0;
-    lock                     = 0;
 }

-void DatabaseCoreBackendPrivate::init(const QString& name, DatabaseLocking* const l)
+DatabaseCoreBackendPrivate::~DatabaseCoreBackendPrivate()
 {
-    QObject::connect(QCoreApplication::instance(), SIGNAL(aboutToQuit()),
-                     q, SLOT(slotMainThreadFinished()));
+    // Must be shut down from the main thread.
+    // Clean up the QThreadStorage. It deletes any stored data.
+    threadDataStorage.setLocalData(0);
+}

+void DatabaseCoreBackendPrivate::init(const QString& name, DatabaseLocking* const l)
+{
     backendName = name;
     lock        = l;

@@ -133,84 +170,44 @@ void DatabaseCoreBackendPrivate::init(const QString& name, DatabaseLocking* cons
 // finishing of the thread.
 QSqlDatabase DatabaseCoreBackendPrivate::databaseForThread()
 {
-    QThread* const thread = QThread::currentThread();
-    QSqlDatabase db       = threadDatabases[thread];
-    int isValid           = databasesValid[thread];
-
-    if (!isValid || !db.isOpen())
+    DatabaseThreadData* threadData = 0;
+    if (!threadDataStorage.hasLocalData())
     {
-        // need to open a db for thread
-        bool success = open(db);
-
-        if (!success)
-        {
-            kDebug() << "Error while opening the database. Details: [" << db.lastError() << "]";
-        }
-
-        QObject::connect(thread, SIGNAL(finished()),
-                         q, SLOT(slotThreadFinished()));
+        threadData = new DatabaseThreadData;
+        threadDataStorage.setLocalData(threadData);
     }
-
-#ifdef DATABASCOREBACKEND_DEBUG
     else
     {
-        kDebug() << "Database ["<< connectionName(thread) <<"] already open for thread ["<< thread <<"].";
+        threadData = threadDataStorage.localData();
     }

-#endif
-
-    return db;
-}
-
-void DatabaseCoreBackendPrivate::closeDatabaseForThread()
-{
-    QThread* const thread = QThread::currentThread();
+    // do we need to reopen the database because parameter changed and validity was increased?
+    if (threadData->valid && threadData->valid < currentValidity)
+    {
+        threadData->closeDatabase();
+    }

-    // scope, so that db is destructed when calling removeDatabase
+    if (!threadData->valid || !threadData->database.isOpen())
     {
-        QSqlDatabase db = threadDatabases[thread];
+        threadData->database = createDatabaseConnection();

-        if (db.isValid())
+        if (threadData->database.open())
         {
-            db.close();
+            threadData->valid = currentValidity;
+        }
+        else
+        {
+            kDebug() << "Error while opening the database. Error was" << threadData->database.lastError();
         }
     }

-    threadDatabases.remove(thread);
-    databaseErrors.remove(thread);
-    databasesValid[thread] = 0;
-    transactionCount.remove(thread);
-    QSqlDatabase::removeDatabase(connectionName(thread));
-}
-
-QSqlError DatabaseCoreBackendPrivate::databaseErrorForThread()
-{
-    QThread* const thread = QThread::currentThread();
-    return databaseErrors[thread];
-}
-
-void DatabaseCoreBackendPrivate::setDatabaseErrorForThread(const QSqlError& lastError)
-{
-    QThread* const thread = QThread::currentThread();
-    databaseErrors.insert(thread, lastError);
-}
-
-QString DatabaseCoreBackendPrivate::connectionName(QThread* const thread)
-{
-    return backendName + QString::number((quintptr)thread);
+    return threadData->database;
 }

-bool DatabaseCoreBackendPrivate::open(QSqlDatabase& db)
+QSqlDatabase DatabaseCoreBackendPrivate::createDatabaseConnection()
 {
-    if (db.isValid())
-    {
-        db.close();
-    }
-
-    QThread* const thread = QThread::currentThread();
-    db                    = QSqlDatabase::addDatabase(parameters.databaseType, connectionName(thread));
-
-    QString connectOptions;// = parameters.connectOptions;
+    QSqlDatabase db        = QSqlDatabase::addDatabase(parameters.databaseType, connectionName());
+    QString connectOptions = parameters.connectOptions;

     if (parameters.isSQLite())
     {
@@ -230,55 +227,48 @@ bool DatabaseCoreBackendPrivate::open(QSqlDatabase& db)

     db.setDatabaseName(parameters.databaseName);
     db.setConnectOptions(connectOptions);
-    /*db.setHostName(parameters.hostName);
-    db.setPort(parameters.port);
-    db.setUserName(parameters.userName);
-    db.setPassword(parameters.password);*/

-    bool success = db.open();
+    return db;
+}

-    if (success)
+void DatabaseCoreBackendPrivate::closeDatabaseForThread()
+{
+    if (threadDataStorage.hasLocalData())
     {
-        db.exec("PRAGMA synchronous=1;");
+        threadDataStorage.localData()->closeDatabase();
     }
-    else
+}
+
+QSqlError DatabaseCoreBackendPrivate::databaseErrorForThread()
+{
+    if (threadDataStorage.hasLocalData())
     {
-        kDebug() << "Error while opening the database. Error was <" << db.lastError() << ">";
+        return threadDataStorage.localData()->lastError;
     }
-
-    threadDatabases[thread]  = db;
-    databasesValid[thread]   = 1;
-    transactionCount[thread] = 0;
-
-    return success;
+    return QSqlError();
 }

-bool DatabaseCoreBackendPrivate::incrementTransactionCount()
+void DatabaseCoreBackendPrivate::setDatabaseErrorForThread(const QSqlError& lastError)
 {
-    QThread* const thread = QThread::currentThread();
-    return !transactionCount[thread]++;
+    if (threadDataStorage.hasLocalData())
+    {
+        threadDataStorage.localData()->lastError = lastError;
+    }
 }

-bool DatabaseCoreBackendPrivate::decrementTransactionCount()
+QString DatabaseCoreBackendPrivate::connectionName()
 {
-    QThread* const thread = QThread::currentThread();
-    return !--transactionCount[thread];
+    return backendName + QString::number((quintptr)QThread::currentThread());
 }

-bool DatabaseCoreBackendPrivate::isInTransactionInOtherThread() const
+bool DatabaseCoreBackendPrivate::incrementTransactionCount()
 {
-    QThread* const thread = QThread::currentThread();
-    QHash<QThread*, int>::const_iterator it;
-
-    for (it = transactionCount.constBegin(); it != transactionCount.constEnd(); ++it)
-    {
-        if (it.key() != thread && it.value())
-        {
-            return true;
-        }
-    }
+    return (!threadDataStorage.localData()->transactionCount++);
+}

-    return false;
+bool DatabaseCoreBackendPrivate::decrementTransactionCount()
+{
+    return (!--threadDataStorage.localData()->transactionCount);
 }

 bool DatabaseCoreBackendPrivate::isInMainThread() const
@@ -295,7 +285,7 @@ bool DatabaseCoreBackendPrivate::isInUIThread() const
         return false;
     }

-    return QThread::currentThread() == app->thread();
+    return (QThread::currentThread() == app->thread());
 }

 bool DatabaseCoreBackendPrivate::reconnectOnError() const
@@ -325,7 +315,8 @@ bool DatabaseCoreBackendPrivate::isConnectionError(const SqlQuery& query) const
         return false;
     }

-    return (query.lastError().type() == QSqlError::ConnectionError || query.lastError().number()==2006);
+    return query.lastError().type()   == QSqlError::ConnectionError ||
+           query.lastError().number() == 2006;
 }

 bool DatabaseCoreBackendPrivate::needToConsultUserForError(const SqlQuery&) const
@@ -336,12 +327,15 @@ bool DatabaseCoreBackendPrivate::needToConsultUserForError(const SqlQuery&) cons

 bool DatabaseCoreBackendPrivate::needToHandleWithErrorHandler(const SqlQuery& query) const
 {
-    return isConnectionError(query) || needToConsultUserForError(query);
+    return (isConnectionError(query) || needToConsultUserForError(query));
 }

 bool DatabaseCoreBackendPrivate::checkRetrySQLiteLockError(int retries)
 {
-    kDebug() << "Database is locked. Waited" << retries*10;
+    if (!(retries % 25))
+    {
+        kDebug() << "Database is locked. Waited" << retries*10;
+    }

     const int uiMaxRetries = 50;
     const int maxRetries   = 1000;
@@ -476,7 +470,7 @@ bool DatabaseCoreBackendPrivate::handleWithErrorHandler(const SqlQuery* const qu
     }
     else
     {
-        //TODO check if it's better to use an own error handler for kio slaves.
+        // TODO check if it's better to use an own error handler for kio slaves.
         // But for now, close only the database in the hope, that the next
         // access will be successful.
         closeDatabaseForThread();
@@ -755,18 +749,6 @@ void DatabaseCoreBackend::setDatabaseErrorHandler(DatabaseErrorHandler* const ha
     d->errorHandler = handler;
 }

-void DatabaseCoreBackend::slotThreadFinished()
-{
-    Q_D(DatabaseCoreBackend);
-    d->closeDatabaseForThread();
-}
-
-void DatabaseCoreBackend::slotMainThreadFinished()
-{
-    Q_D(DatabaseCoreBackend);
-    d->closeDatabaseForThread();
-}
-
 bool DatabaseCoreBackend::isCompatible(const DatabaseParameters& parameters)
 {
     return QSqlDatabase::drivers().contains(parameters.databaseType);
@@ -776,10 +758,8 @@ bool DatabaseCoreBackend::open(const DatabaseParameters& parameters)
 {
     Q_D(DatabaseCoreBackend);
     d->parameters = parameters;
-
-    // Force possibly opened thread dbs to re-open with new parameters.
-    // They are not accessible from this thread!
-    d->databasesValid.clear();
+    // This will make possibly opened thread dbs reload at next access
+    d->currentValidity++;

     int retries = 0;

@@ -913,7 +893,7 @@ DatabaseCoreBackend::QueryState DatabaseCoreBackend::handleQueryResult(SqlQuery&
     return DatabaseCoreBackend::NoErrors;
 }

-// ----------------------------------------------------------------------------------------------------
+// -------------------------------------------------------------------------------------

 DatabaseCoreBackend::QueryState DatabaseCoreBackend::execSql(const QString& sql, QList<QVariant>* const values, QVariant* const lastInsertId)
 {
@@ -922,52 +902,54 @@ DatabaseCoreBackend::QueryState DatabaseCoreBackend::execSql(const QString& sql,
 }

 DatabaseCoreBackend::QueryState DatabaseCoreBackend::execSql(const QString& sql, const QVariant& boundValue1,
-        QList<QVariant>* const values, QVariant* const lastInsertId)
+                                                             QList<QVariant>* const values, QVariant* const lastInsertId)
 {
     SqlQuery query = execQuery(sql, boundValue1);
     return handleQueryResult(query, values, lastInsertId);
 }

 DatabaseCoreBackend::QueryState DatabaseCoreBackend::execSql(const QString& sql,
-        const QVariant& boundValue1, const QVariant& boundValue2,
-        QList<QVariant>* const values, QVariant* const lastInsertId)
+                                                             const QVariant& boundValue1, const QVariant& boundValue2,
+                                                             QList<QVariant>* const values, QVariant* const lastInsertId)
 {
     SqlQuery query = execQuery(sql, boundValue1, boundValue2);
     return handleQueryResult(query, values, lastInsertId);
 }

 DatabaseCoreBackend::QueryState DatabaseCoreBackend::execSql(const QString& sql,
-        const QVariant& boundValue1, const QVariant& boundValue2,
-        const QVariant& boundValue3, QList<QVariant>* const values,
-        QVariant* const lastInsertId)
+                                                             const QVariant& boundValue1, const QVariant& boundValue2,
+                                                             const QVariant& boundValue3, QList<QVariant>* const values,
+                                                             QVariant* const lastInsertId)
 {
     SqlQuery query = execQuery(sql, boundValue1, boundValue2, boundValue3);
     return handleQueryResult(query, values, lastInsertId);
 }

 DatabaseCoreBackend::QueryState DatabaseCoreBackend::execSql(const QString& sql,
-        const QVariant& boundValue1, const QVariant& boundValue2,
-        const QVariant& boundValue3, const QVariant& boundValue4,
-        QList<QVariant>* const values, QVariant* const lastInsertId)
+                                                             const QVariant& boundValue1, const QVariant& boundValue2,
+                                                             const QVariant& boundValue3, const QVariant& boundValue4,
+                                                             QList<QVariant>* const values, QVariant* const lastInsertId)
 {
     SqlQuery query = execQuery(sql, boundValue1, boundValue2, boundValue3, boundValue4);
     return handleQueryResult(query, values, lastInsertId);
 }

 DatabaseCoreBackend::QueryState DatabaseCoreBackend::execSql(const QString& sql, const QList<QVariant>& boundValues,
-        QList<QVariant>* const values, QVariant* const lastInsertId)
+                                                             QList<QVariant>* const values, QVariant* const lastInsertId)
 {
     SqlQuery query = execQuery(sql, boundValues);
     return handleQueryResult(query, values, lastInsertId);
 }

 DatabaseCoreBackend::QueryState DatabaseCoreBackend::execSql(const QString& sql, const QMap<QString, QVariant>& bindingMap,
-        QList<QVariant>* const values, QVariant* const lastInsertId)
+                                                             QList<QVariant>* const values, QVariant* const lastInsertId)
 {
     SqlQuery query = execQuery(sql, bindingMap);
     return handleQueryResult(query, values, lastInsertId);
 }

+// -------------------------------------------------------------------------------------
+
 DatabaseCoreBackend::QueryState DatabaseCoreBackend::execSql(SqlQuery& preparedQuery, QList<QVariant>* const values, QVariant* const lastInsertId)
 {
     exec(preparedQuery);
@@ -1014,6 +996,8 @@ DatabaseCoreBackend::QueryState DatabaseCoreBackend::execSql(SqlQuery& preparedQ
     return handleQueryResult(preparedQuery, values, lastInsertId);
 }

+// -------------------------------------------------------------------------------------
+
 SqlQuery DatabaseCoreBackend::execQuery(const QString& sql, const QVariant& boundValue1)
 {
     SqlQuery query = prepareQuery(sql);
@@ -1066,6 +1050,8 @@ SqlQuery DatabaseCoreBackend::execQuery(const QString& sql)
     return query;
 }

+// -------------------------------------------------------------------------------------
+
 void DatabaseCoreBackend::execQuery(SqlQuery& query, const QVariant& boundValue1)
 {
     query.bindValue(0, boundValue1);
@@ -1111,6 +1097,8 @@ void DatabaseCoreBackend::execQuery(SqlQuery& query, const QList<QVariant>& boun
     exec(query);
 }

+// -------------------------------------------------------------------------------------
+
 SqlQuery DatabaseCoreBackend::execQuery(const QString& sql, const QMap<QString, QVariant>& bindingMap)
 {
     QString preparedString = sql;
@@ -1252,7 +1240,7 @@ SqlQuery DatabaseCoreBackend::execQuery(const QString& sql, const QMap<QString,

     SqlQuery query = prepareQuery(preparedString);

-    for (int i=0; i<valuesToBind.size(); ++i)
+    for (int i=0; i < valuesToBind.size(); ++i)
     {
         query.bindValue(i, valuesToBind.at(i));
     }
@@ -1262,12 +1250,12 @@ SqlQuery DatabaseCoreBackend::execQuery(const QString& sql, const QMap<QString,
 }

 DatabaseCoreBackend::QueryState DatabaseCoreBackend::execUpsertDBAction(const DatabaseAction& action, const QVariant& id,
-        const QStringList fieldNames, const QList<QVariant>& values)
+                                                                        const QStringList fieldNames, const QList<QVariant>& values)
 {
     QMap<QString, QVariant> parameters;
     QMap<QString, QVariant> fieldValueMap;

-    for (int i=0; i<fieldNames.size(); ++i)
+    for (int i = 0; i < fieldNames.size(); ++i)
     {
         fieldValueMap.insert(fieldNames.at(i), values.at(i));
     }
@@ -1285,7 +1273,7 @@ DatabaseCoreBackend::QueryState DatabaseCoreBackend::execUpsertDBAction(const Da
 }

 DatabaseCoreBackend::QueryState DatabaseCoreBackend::execUpsertDBAction(const QString& action, const QVariant& id,
-        const QStringList fieldNames, const QList<QVariant>& values)
+                                                                        const QStringList fieldNames, const QList<QVariant>& values)
 {
     return execUpsertDBAction(getDBAction(action), id, fieldNames, values);
 }
@@ -1516,6 +1504,7 @@ SqlQuery DatabaseCoreBackend::copyQuery(const SqlQuery& old)
 #endif
     query.prepare(old.lastQuery());
     query.setForwardOnly(old.isForwardOnly());
+
     // only for positional binding
     QList<QVariant> boundValues = old.boundValues().values();

@@ -1635,7 +1624,7 @@ DatabaseCoreBackend::QueryState DatabaseCoreBackend::commitTransaction()
 bool DatabaseCoreBackend::isInTransaction() const
 {
     Q_D(const DatabaseCoreBackend);
-    return d->isInTransactionInOtherThread();
+    return d->isInTransaction;
 }

 void DatabaseCoreBackend::rollbackTransaction()
@@ -1663,4 +1652,18 @@ QString DatabaseCoreBackend::lastError()
     return d->databaseForThread().lastError().text();
 }

+int DatabaseCoreBackend::maximumBoundValues() const
+{
+    Q_D(const DatabaseCoreBackend);
+
+    if (d->parameters.isSQLite())
+    {
+        return 999;   // SQLITE_MAX_VARIABLE_NUMBER
+    }
+    else
+    {
+        return 65535; // MySQL
+    }
+}
+
 } // namespace KFaceIface
diff --git a/libkface/database/databasecorebackend.h b/libkface/database/databasecorebackend.h
index 9ce859a..a1beac3 100644
--- a/libkface/database/databasecorebackend.h
+++ b/libkface/database/databasecorebackend.h
@@ -44,6 +44,7 @@ namespace KFaceIface
 {

 class DatabaseCoreBackendPrivate;
+class DatabaseErrorHandler;
 class SchemaUpdater;

 class DatabaseLocking
@@ -147,17 +148,18 @@ public:
      */
     void close();

-    // -----------------------------------------------------------
+public:

     class QueryState
     {
     public:

-        QueryState() : value(DatabaseCoreBackend::NoErrors)
+        QueryState()
+            : value(DatabaseCoreBackend::NoErrors)
         {
         }

-        QueryState(QueryStateEnum value)
+        QueryState(const QueryStateEnum value)
             : value(value)
         {
         }
@@ -177,6 +179,8 @@ public:
         QueryStateEnum value;
     };

+public:
+
     /**
      * Returns the current status of the database backend
      */
@@ -275,10 +279,8 @@ public:
                        const QVariant& boundValue1, const QVariant& boundValue2,
                        const QVariant& boundValue3, const QVariant& boundValue4,
                        QList<QVariant>* const values = 0, QVariant* const lastInsertId = 0);
-    QueryState execSql(const QString& sql,
-                       const QList<QVariant>& boundValues,
-                       QList<QVariant>* const values = 0,
-                       QVariant* const lastInsertId = 0);
+    QueryState execSql(const QString& sql, const QList<QVariant>& boundValues,
+                       QList<QVariant>* const values = 0, QVariant* const lastInsertId = 0);

     QueryState execSql(SqlQuery& preparedQuery, QList<QVariant>* const values = 0, QVariant* const lastInsertId = 0);
     QueryState execSql(SqlQuery& preparedQuery, const QVariant& boundValue1,
@@ -438,6 +440,12 @@ public:
      */
     QSqlError lastSQLError();

+    /**
+     * Returns the maximum number of bound parameters allowed per query.
+     * This value depends on the database engine.
+     */
+    int maximumBoundValues() const;
+
     /*
         Qt SQL driver supported features
         SQLITE3:
@@ -462,11 +470,6 @@ public:
             LastInsertId
     */

-private Q_SLOTS:
-
-    void slotThreadFinished();
-    void slotMainThreadFinished();
-
 protected:

     DatabaseCoreBackendPrivate* const d_ptr;
diff --git a/libkface/database/databasecorebackend_p.h b/libkface/database/databasecorebackend_p.h
index c39b33f..27faaa5 100644
--- a/libkface/database/databasecorebackend_p.h
+++ b/libkface/database/databasecorebackend_p.h
@@ -29,6 +29,7 @@
 #include <QHash>
 #include <QSqlDatabase>
 #include <QThread>
+#include <QThreadStorage>
 #include <QWaitCondition>

 // Local includes
@@ -38,40 +39,54 @@
 namespace KFaceIface
 {

+class DatabaseThreadData
+{
+public:
+
+    DatabaseThreadData();
+    ~DatabaseThreadData();
+
+    void closeDatabase();
+
+    QSqlDatabase database;
+    int          valid;
+    int          transactionCount;
+    QSqlError    lastError;
+};
+
 class DatabaseCoreBackendPrivate : public DatabaseErrorAnswer
 {
 public:

-    DatabaseCoreBackendPrivate(DatabaseCoreBackend* const backend);
-    virtual ~DatabaseCoreBackendPrivate() {}
+    explicit DatabaseCoreBackendPrivate(DatabaseCoreBackend* const backend);
+    virtual ~DatabaseCoreBackendPrivate();

     void init(const QString& connectionName, DatabaseLocking* const locking);

-    QString connectionName(QThread* const thread);
+    QString connectionName();

     QSqlDatabase databaseForThread();
     QSqlError    databaseErrorForThread();
     void         setDatabaseErrorForThread(const QSqlError& lastError);

+    QSqlDatabase createDatabaseConnection();
     void closeDatabaseForThread();
-    bool open(QSqlDatabase& db);
     bool incrementTransactionCount();
     bool decrementTransactionCount();
-    bool isInTransactionInOtherThread() const;

     bool isInMainThread() const;
-    bool isInUIThread() const;
+    bool isInUIThread()   const;

-    bool reconnectOnError() const;
-    bool isSQLiteLockError(const SqlQuery& query) const;
+    bool reconnectOnError()                                       const;
+    bool isSQLiteLockError(const SqlQuery& query)                 const;
     bool isSQLiteLockTransactionError(const QSqlError& lastError) const;
-    bool checkRetrySQLiteLockError(int retries);
-    bool isConnectionError(const SqlQuery& query) const;
-    bool needToConsultUserForError(const SqlQuery& query) const;
-    bool needToHandleWithErrorHandler(const SqlQuery& query) const;
-    void debugOutputFailedQuery(const QSqlQuery& query) const;
-    void debugOutputFailedTransaction(const QSqlError& error) const;
+    bool isConnectionError(const SqlQuery& query)                 const;
+    bool needToConsultUserForError(const SqlQuery& query)         const;
+    bool needToHandleWithErrorHandler(const SqlQuery& query)      const;
+    void debugOutputFailedQuery(const QSqlQuery& query)           const;
+    void debugOutputFailedTransaction(const QSqlError& error)     const;

+    bool checkRetrySQLiteLockError(int retries);
     bool checkOperationStatus();
     bool handleWithErrorHandler(const SqlQuery* const query);
     void setQueryOperationFlag(DatabaseCoreBackend::QueryOperationStatus status);
@@ -80,19 +95,14 @@ public:
     // called by DatabaseErrorHandler, implementing DatabaseErrorAnswer
     virtual void connectionErrorContinueQueries();
     virtual void connectionErrorAbortQueries();
-
     virtual void transactionFinished();

 public:

-    // this is always accessed in mutex context, no need for QThreadStorage
-    QHash<QThread*, QSqlDatabase>             threadDatabases;
-    // this is not only db.isValid(), but also "parameters changed, need to reopen"
-    QHash<QThread*, int>                      databasesValid;
-    // for recursive transactions
-    QHash<QThread*, int>                      transactionCount;
+    QThreadStorage<DatabaseThreadData*>       threadDataStorage;

-    QHash<QThread*, QSqlError>                databaseErrors;
+    // This compares to DatabaseThreadData's valid. If currentValidity is increased and > valid, the db is marked as invalid
+    int                                       currentValidity;

     bool                                      isInTransaction;

@@ -121,7 +131,7 @@ public :
     {
     public:

-        AbstractUnlocker(DatabaseCoreBackendPrivate* const d);
+        explicit AbstractUnlocker(DatabaseCoreBackendPrivate* const d);
         ~AbstractUnlocker();

         void finishAcquire();
@@ -157,7 +167,7 @@ public :
     {
     public:

-        ErrorLocker(DatabaseCoreBackendPrivate* const d);
+        explicit ErrorLocker(DatabaseCoreBackendPrivate* const d);
         void wait();
     };

@@ -167,7 +177,7 @@ public :
     {
     public:

-        BusyWaiter(DatabaseCoreBackendPrivate* const d);
+        explicit BusyWaiter(DatabaseCoreBackendPrivate* const d);
     };

 public :
diff --git a/libkface/database/databaseparameters.h b/libkface/database/databaseparameters.h
index 655b87a..7cf84ec 100644
--- a/libkface/database/databaseparameters.h
+++ b/libkface/database/databaseparameters.h
@@ -52,6 +52,7 @@ public:

     QString databaseType;
     QString databaseName;
+    QString connectOptions;

     bool operator==(const DatabaseParameters& other) const;
     bool operator!=(const DatabaseParameters& other) const;
Comment 32 caulier.gilles 2014-12-15 12:57:53 UTC
Git commit 0fb2b35c650b20f7c208bb5b07bd701fd4d09d1f by Marcel Wiesweg.
Committed on 15/11/2014 at 14:46.
Pushed by mwiesweg into branch 'master'.

Back and forward port code polish and style changes from libkface db backend.
The files have now only the needed minor differences

M  +140  -136  libs/database/core/databasecorebackend.cpp
M  +6    -9    libs/database/core/databasecorebackend.h
M  +4    -5    libs/database/core/databasecorebackend_p.h

http://commits.kde.org/digikam/0fb2b35c650b20f7c208bb5b07bd701fd4d09d1f

diff --git a/libs/database/core/databasecorebackend.cpp b/libs/database/core/databasecorebackend.cpp
index 76a958a..480f437 100644
--- a/libs/database/core/databasecorebackend.cpp
+++ b/libs/database/core/databasecorebackend.cpp
@@ -6,7 +6,7 @@
  * Date        : 2007-04-15
  * Description : Abstract database backend
  *
- * Copyright (C) 2007-2010 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de>
+ * Copyright (C) 2007-2012 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de>
  *
  * This program is free software; you can redistribute it
  * and/or modify it under the terms of the GNU General
@@ -42,22 +42,23 @@
 // KDE includes

 #include <kdebug.h>
-#include <kglobal.h>

 // Local includes

-#include "thumbnailschemaupdater.h"
 #include "dbactiontype.h"
+#include "thumbnailschemaupdater.h"

-//#define DATABASCOREBACKEND_DEBUG 1
 namespace Digikam
 {

 DatabaseLocking::DatabaseLocking()
-    : mutex(QMutex::Recursive), lockCount(0) // create a recursive mutex
+    : mutex(QMutex::Recursive),
+      lockCount(0) // create a recursive mutex
 {
 }

+// -----------------------------------------------------------------------------------------
+
 // For whatever reason, these methods are "static protected"
 class sotoSleep : public QThread
 {
@@ -79,6 +80,23 @@ public:
     }
 };

+// -----------------------------------------------------------------------------------------
+
+DatabaseCoreBackendPrivate::BusyWaiter::BusyWaiter(DatabaseCoreBackendPrivate* const d)
+    : AbstractWaitingUnlocker(d, &d->busyWaitMutex, &d->busyWaitCondVar)
+{
+}
+
+// -----------------------------------------------------------------------------------------
+
+DatabaseCoreBackendPrivate::ErrorLocker::ErrorLocker(DatabaseCoreBackendPrivate* const d)
+    : AbstractWaitingUnlocker(d, &d->errorLockMutex, &d->errorLockCondVar)
+{
+}
+
+// -----------------------------------------------------------------------------------------
+
+
 DatabaseThreadData::DatabaseThreadData()
     : valid(0),
       transactionCount(0)
@@ -288,7 +306,7 @@ bool DatabaseCoreBackendPrivate::isSQLiteLockError(const SqlQuery& query) const
 bool DatabaseCoreBackendPrivate::isSQLiteLockTransactionError(const QSqlError& lastError) const
 {
     return parameters.isSQLite() &&
-           lastError.type() == QSqlError::TransactionError &&
+           lastError.type()         == QSqlError::TransactionError &&
            lastError.databaseText() == QLatin1String("database is locked");
     // wouldnt it be great if they gave us the database error number...
 }
@@ -356,74 +374,6 @@ void DatabaseCoreBackendPrivate::debugOutputFailedTransaction(const QSqlError& e
              << error.number() << error.type();
 }

-
-DatabaseCoreBackendPrivate::AbstractUnlocker::AbstractUnlocker(DatabaseCoreBackendPrivate* const d)
-    : count(0), d(d)
-{
-    // Why two mutexes? The main mutex is recursive and won't work with a condvar.
-
-    // acquire lock
-    d->lock->mutex.lock();
-    // store lock count
-    count = d->lock->lockCount;
-    // set lock count to 0
-    d->lock->lockCount = 0;
-
-    // unlock
-    for (int i=0; i<count; ++i)
-    {
-        d->lock->mutex.unlock();
-    }
-}
-
-void DatabaseCoreBackendPrivate::AbstractUnlocker::finishAcquire()
-{
-    // drop lock acquired in first line. Main mutex is now free.
-    // We maintain lock order (first main mutex, second error lock mutex)
-    // but we drop main mutex lock for waiting on the cond var.
-    d->lock->mutex.unlock();
-}
-
-DatabaseCoreBackendPrivate::AbstractUnlocker::~AbstractUnlocker()
-{
-    // lock main mutex as often as it was locked before
-    for (int i=0; i<count; ++i)
-    {
-        d->lock->mutex.lock();
-    }
-
-    // update lock count
-    d->lock->lockCount += count;
-}
-
-DatabaseCoreBackendPrivate::AbstractWaitingUnlocker::AbstractWaitingUnlocker(DatabaseCoreBackendPrivate* const d,
-                                                                             QMutex* const mutex, QWaitCondition* const condVar)
-    : AbstractUnlocker(d), mutex(mutex), condVar(condVar)
-{
-    // Why two mutexes? The main mutex is recursive and won't work with a condvar.
-    // lock condvar mutex (lock only if main mutex is locked)
-    mutex->lock();
-
-    finishAcquire();
-}
-
-DatabaseCoreBackendPrivate::AbstractWaitingUnlocker::~AbstractWaitingUnlocker()
-{
-    // unlock condvar mutex. Both mutexes are now free.
-    mutex->unlock();
-    // now base class destructor is executed, reallocating main mutex
-}
-
-bool DatabaseCoreBackendPrivate::AbstractWaitingUnlocker::wait(unsigned long time)
-{
-    return condVar->wait(mutex, time);
-}
-
-DatabaseCoreBackendPrivate::BusyWaiter::BusyWaiter(DatabaseCoreBackendPrivate* const d)
-    : AbstractWaitingUnlocker(d, &d->busyWaitMutex, &d->busyWaitCondVar)
-{
-}
-
 void DatabaseCoreBackendPrivate::transactionFinished()
 {
     // wakes up any BusyWaiter waiting on the busyWaitCondVar.
@@ -431,39 +381,18 @@ void DatabaseCoreBackendPrivate::transactionFinished()
     busyWaitCondVar.wakeOne();
 }

-DatabaseCoreBackendPrivate::ErrorLocker::ErrorLocker(DatabaseCoreBackendPrivate* const d)
-    : AbstractWaitingUnlocker(d, &d->errorLockMutex, &d->errorLockCondVar)
-{
-}
-
-/** This suspends the current thread if the query status as
- *  set by setFlag() is Wait and until the thread is woken with wakeAll().
- *  The DatabaseAccess mutex will be unlocked while waiting.
- */
-void DatabaseCoreBackendPrivate::ErrorLocker::wait()
-{
-    // we use a copy of the flag under lock of the errorLockMutex to be able to check it here
-    while (d->errorLockOperationStatus == DatabaseCoreBackend::Wait)
-    {
-        wait();
-    }
-}
-
-/** Set the wait flag to queryStatus. Typically, call this with Wait.
- */
+/** Set the wait flag to queryStatus. Typically, call this with Wait. */
 void DatabaseCoreBackendPrivate::setQueryOperationFlag(DatabaseCoreBackend::QueryOperationStatus status)
 {
     // Enforce lock order (first main mutex, second error lock mutex)
     QMutexLocker l(&errorLockMutex);
-
     // this change must be done under errorLockMutex lock
     errorLockOperationStatus = status;
     operationStatus          = status;
 }

 /** Set the wait flag to queryStatus and wake all waiting threads.
- *  Typically, call wakeAll with status ExecuteNormal or AbortQueries.
- */
+ *  Typically, call wakeAll with status ExecuteNormal or AbortQueries. */
 void DatabaseCoreBackendPrivate::queryOperationWakeAll(DatabaseCoreBackend::QueryOperationStatus status)
 {
     QMutexLocker l(&errorLockMutex);
@@ -530,7 +459,7 @@ bool DatabaseCoreBackendPrivate::handleWithErrorHandler(const SqlQuery* const qu
         }
         else
         {
-            kError() << "Failed to invoke DatabaseErrorHandler. Aborting all queries.";
+            kWarning() << "Failed to invoke DatabaseErrorHandler. Aborting all queries.";
             operationStatus = DatabaseCoreBackend::AbortQueries;
         }

@@ -568,7 +497,88 @@ void DatabaseCoreBackendPrivate::connectionErrorAbortQueries()
     queryOperationWakeAll(DatabaseCoreBackend::AbortQueries);
 }

-// -----------------------------------------------------------------------------------------------
+// -----------------------------------------------------------------------------------------
+
+DatabaseCoreBackendPrivate::AbstractUnlocker::AbstractUnlocker(DatabaseCoreBackendPrivate* const d)
+    : count(0), d(d)
+{
+    // Why two mutexes? The main mutex is recursive and won't work with a condvar.
+
+    // acquire lock
+    d->lock->mutex.lock();
+    // store lock count
+    count = d->lock->lockCount;
+    // set lock count to 0
+    d->lock->lockCount = 0;
+
+    // unlock
+    for (int i=0; i<count; ++i)
+    {
+        d->lock->mutex.unlock();
+    }
+}
+
+void DatabaseCoreBackendPrivate::AbstractUnlocker::finishAcquire()
+{
+    // drop lock acquired in first line. Main mutex is now free.
+    // We maintain lock order (first main mutex, second error lock mutex)
+    // but we drop main mutex lock for waiting on the cond var.
+    d->lock->mutex.unlock();
+}
+
+DatabaseCoreBackendPrivate::AbstractUnlocker::~AbstractUnlocker()
+{
+    // lock main mutex as often as it was locked before
+    for (int i=0; i<count; ++i)
+    {
+        d->lock->mutex.lock();
+    }
+
+    // update lock count
+    d->lock->lockCount += count;
+}
+
+// -----------------------------------------------------------------------------------------
+
+DatabaseCoreBackendPrivate::AbstractWaitingUnlocker::AbstractWaitingUnlocker(DatabaseCoreBackendPrivate* const d,
+        QMutex* const mutex, QWaitCondition* const condVar)
+    : AbstractUnlocker(d), mutex(mutex), condVar(condVar)
+{
+    // Why two mutexes? The main mutex is recursive and won't work with a condvar.
+    // lock condvar mutex (lock only if main mutex is locked)
+    mutex->lock();
+
+    finishAcquire();
+}
+
+DatabaseCoreBackendPrivate::AbstractWaitingUnlocker::~AbstractWaitingUnlocker()
+{
+    // unlock condvar mutex. Both mutexes are now free.
+    mutex->unlock();
+    // now base class destructor is executed, reallocating main mutex
+}
+
+bool DatabaseCoreBackendPrivate::AbstractWaitingUnlocker::wait(unsigned long time)
+{
+    return condVar->wait(mutex, time);
+}
+
+// -----------------------------------------------------------------------------------------
+
+/** This suspends the current thread if the query status as
+ *  set by setFlag() is Wait and until the thread is woken with wakeAll().
+ *  The DatabaseAccess mutex will be unlocked while waiting.
+ */
+void DatabaseCoreBackendPrivate::ErrorLocker::wait()
+{
+    // we use a copy of the flag under lock of the errorLockMutex to be able to check it here
+    while (d->errorLockOperationStatus == DatabaseCoreBackend::Wait)
+    {
+        wait();
+    }
+}
+
+// -----------------------------------------------------------------------------------------

 DatabaseCoreBackend::DatabaseCoreBackend(const QString& backendName, DatabaseLocking* const locking)
     : d_ptr(new DatabaseCoreBackendPrivate(this))
@@ -602,33 +612,32 @@ DatabaseAction DatabaseCoreBackend::getDBAction(const QString& actionName) const

     if (action.name.isNull())
     {
-        kError() << "No DB action defined for" << actionName << "! Implementation missing for this database type.";
+        kWarning() << "No DB action defined for" << actionName << "! Implementation missing for this database type.";
     }

     return action;
 }

 DatabaseCoreBackend::QueryState DatabaseCoreBackend::execDBAction(const DatabaseAction& action, QList<QVariant>* const values,
-        QVariant* const lastInsertId)
+                                                                  QVariant* const lastInsertId)
 {
     return execDBAction(action, QMap<QString, QVariant>(), values, lastInsertId);
 }

 DatabaseCoreBackend::QueryState DatabaseCoreBackend::execDBAction(const QString& action, QList<QVariant>* const values,
-        QVariant* const lastInsertId)
+                                                                  QVariant* const lastInsertId)
 {
     return execDBAction(getDBAction(action), QMap<QString, QVariant>(), values, lastInsertId);
 }

 DatabaseCoreBackend::QueryState DatabaseCoreBackend::execDBAction(const QString& action, const QMap<QString, QVariant>& bindingMap,
-        QList<QVariant>* const values, QVariant* const lastInsertId)
+                                                                  QList<QVariant>* const values, QVariant* const lastInsertId)
 {
     return execDBAction(getDBAction(action), bindingMap, values, lastInsertId);
 }

-DatabaseCoreBackend::QueryState DatabaseCoreBackend::execDBAction(const DatabaseAction& action, const QMap<QString,
-                                                                  QVariant>& bindingMap, QList<QVariant>* const values,
-                                                                  QVariant* const lastInsertId)
+DatabaseCoreBackend::QueryState DatabaseCoreBackend::execDBAction(const DatabaseAction& action, const QMap<QString, QVariant>& bindingMap,
+                                                                  QList<QVariant>* const values, QVariant* const lastInsertId)
 {
     Q_D(DatabaseCoreBackend);

@@ -637,7 +646,7 @@ DatabaseCoreBackend::QueryState DatabaseCoreBackend::execDBAction(const Database

     if (action.name.isNull())
     {
-        kError() << "Attempt to execute null action";
+        kWarning() << "Attempt to execute null action";
         return DatabaseCoreBackend::SQLError;
     }

@@ -726,8 +735,8 @@ QSqlQuery DatabaseCoreBackend::execDBActionQuery(const DatabaseAction& action, c

         if (result.lastError().isValid() && result.lastError().number())
         {
-            kDebug() << "Error while executing DBAction ["<<  action.name
-                     <<"] Statement ["<<actionElement.statement<<"] Errornr. [" << result.lastError() << "]";
+            kDebug() << "Error while executing DBAction [" <<  action.name
+                     << "] Statement [" << actionElement.statement << "] Errornr. [" << result.lastError() << "]";
             break;
         }
     }
@@ -822,7 +831,7 @@ DatabaseCoreBackend::Status DatabaseCoreBackend::status() const
 }

 /*
-bool DatabaseCoreBackend::execSql(const QString& sql, QStringList* values)
+bool DatabaseCoreBackend::execSql(const QString& sql, QStringList* const values)
 {
     QSqlQuery query = execQuery(sql);

@@ -865,8 +874,7 @@ QList<QVariant> DatabaseCoreBackend::readToList(SqlQuery& query)
     return list;
 }

-DatabaseCoreBackend::QueryState DatabaseCoreBackend::handleQueryResult(SqlQuery& query, QList<QVariant>* const values,
-                                                                       QVariant* const lastInsertId)
+DatabaseCoreBackend::QueryState DatabaseCoreBackend::handleQueryResult(SqlQuery& query, QList<QVariant>* const values, QVariant* const lastInsertId)
 {
     if (!query.isActive())
     {
@@ -891,57 +899,54 @@ DatabaseCoreBackend::QueryState DatabaseCoreBackend::handleQueryResult(SqlQuery&

 // -------------------------------------------------------------------------------------

-DatabaseCoreBackend::QueryState DatabaseCoreBackend::execSql(const QString& sql, QList<QVariant>* const values,
-                                                             QVariant* const lastInsertId)
+DatabaseCoreBackend::QueryState DatabaseCoreBackend::execSql(const QString& sql, QList<QVariant>* const values, QVariant* const lastInsertId)
 {
     SqlQuery query = execQuery(sql);
     return handleQueryResult(query, values, lastInsertId);
 }

 DatabaseCoreBackend::QueryState DatabaseCoreBackend::execSql(const QString& sql, const QVariant& boundValue1,
-        QList<QVariant>* values, QVariant* lastInsertId)
+                                                             QList<QVariant>* const values, QVariant* const lastInsertId)
 {
     SqlQuery query = execQuery(sql, boundValue1);
     return handleQueryResult(query, values, lastInsertId);
 }

 DatabaseCoreBackend::QueryState DatabaseCoreBackend::execSql(const QString& sql,
-        const QVariant& boundValue1, const QVariant& boundValue2,
-        QList<QVariant>* const values, QVariant* const lastInsertId)
+                                                             const QVariant& boundValue1, const QVariant& boundValue2,
+                                                             QList<QVariant>* const values, QVariant* const lastInsertId)
 {
     SqlQuery query = execQuery(sql, boundValue1, boundValue2);
     return handleQueryResult(query, values, lastInsertId);
 }

 DatabaseCoreBackend::QueryState DatabaseCoreBackend::execSql(const QString& sql,
-        const QVariant& boundValue1, const QVariant& boundValue2,
-        const QVariant& boundValue3, QList<QVariant>* const values,
-        QVariant* const lastInsertId)
+                                                             const QVariant& boundValue1, const QVariant& boundValue2,
+                                                             const QVariant& boundValue3, QList<QVariant>* const values,
+                                                             QVariant* const lastInsertId)
 {
     SqlQuery query = execQuery(sql, boundValue1, boundValue2, boundValue3);
     return handleQueryResult(query, values, lastInsertId);
 }

 DatabaseCoreBackend::QueryState DatabaseCoreBackend::execSql(const QString& sql,
-        const QVariant& boundValue1, const QVariant& boundValue2,
-        const QVariant& boundValue3, const QVariant& boundValue4,
-        QList<QVariant>* const values, QVariant* const lastInsertId)
+                                                             const QVariant& boundValue1, const QVariant& boundValue2,
+                                                             const QVariant& boundValue3, const QVariant& boundValue4,
+                                                             QList<QVariant>* const values, QVariant* const lastInsertId)
 {
     SqlQuery query = execQuery(sql, boundValue1, boundValue2, boundValue3, boundValue4);
     return handleQueryResult(query, values, lastInsertId);
 }

 DatabaseCoreBackend::QueryState DatabaseCoreBackend::execSql(const QString& sql, const QList<QVariant>& boundValues,
-        QList<QVariant>* const values, QVariant* const lastInsertId)
+                                                             QList<QVariant>* const values, QVariant* const lastInsertId)
 {
     SqlQuery query = execQuery(sql, boundValues);
     return handleQueryResult(query, values, lastInsertId);
 }

-// -------------------------------------------------------------------------------------
-
 DatabaseCoreBackend::QueryState DatabaseCoreBackend::execSql(const QString& sql, const QMap<QString, QVariant>& bindingMap,
-        QList<QVariant>* const values, QVariant* const lastInsertId)
+                                                             QList<QVariant>* const values, QVariant* const lastInsertId)
 {
     SqlQuery query = execQuery(sql, bindingMap);
     return handleQueryResult(query, values, lastInsertId);
@@ -949,8 +954,7 @@ DatabaseCoreBackend::QueryState DatabaseCoreBackend::execSql(const QString& sql,

 // -------------------------------------------------------------------------------------

-DatabaseCoreBackend::QueryState DatabaseCoreBackend::execSql(SqlQuery& preparedQuery,
-                                                             QList<QVariant>* const values, QVariant* const lastInsertId)
+DatabaseCoreBackend::QueryState DatabaseCoreBackend::execSql(SqlQuery& preparedQuery, QList<QVariant>* const values, QVariant* const lastInsertId)
 {
     exec(preparedQuery);
     return handleQueryResult(preparedQuery, values, lastInsertId);
@@ -996,7 +1000,7 @@ DatabaseCoreBackend::QueryState DatabaseCoreBackend::execSql(SqlQuery& preparedQ
     return handleQueryResult(preparedQuery, values, lastInsertId);
 }

-// ----------------------------------------------------------------------------------------
+// -------------------------------------------------------------------------------------

 SqlQuery DatabaseCoreBackend::execQuery(const QString& sql, const QVariant& boundValue1)
 {
@@ -1119,9 +1123,9 @@ SqlQuery DatabaseCoreBackend::execQuery(const QString& sql, const QMap<QString,

             if (!bindingMap.contains(namedPlaceholder))
             {
-                kError() << "Missing place holder" << namedPlaceholder
-                         << "in binding map. The following values are defined for this action:"
-                         << bindingMap.keys() <<". This is a setup error!";
+                kWarning() << "Missing place holder" << namedPlaceholder
+                           << "in binding map. The following values are defined for this action:"
+                           << bindingMap.keys() <<". This is a setup error!";
                 //TODO What should we do here? How can we cancel that action?
             }

@@ -1240,7 +1244,7 @@ SqlQuery DatabaseCoreBackend::execQuery(const QString& sql, const QMap<QString,

     SqlQuery query = prepareQuery(preparedString);

-    for (int i=0; i<valuesToBind.size(); ++i)
+    for (int i=0; i < valuesToBind.size(); ++i)
     {
         query.bindValue(i, valuesToBind.at(i));
     }
@@ -1250,7 +1254,7 @@ SqlQuery DatabaseCoreBackend::execQuery(const QString& sql, const QMap<QString,
 }

 DatabaseCoreBackend::QueryState DatabaseCoreBackend::execUpsertDBAction(const DatabaseAction& action, const QVariant& id,
-        const QStringList fieldNames, const QList<QVariant>& values)
+                                                                        const QStringList fieldNames, const QList<QVariant>& values)
 {
     QMap<QString, QVariant> parameters;
     QMap<QString, QVariant> fieldValueMap;
@@ -1266,7 +1270,7 @@ DatabaseCoreBackend::QueryState DatabaseCoreBackend::execUpsertDBAction(const Da

     parameters.insert(":id",             id);
     parameters.insert(":fieldValueList", qVariantFromValue(fieldValueList));
-    parameters.insert(":fieldList",      qVariantFromValue (fieldList));
+    parameters.insert(":fieldList",      qVariantFromValue(fieldList));
     parameters.insert(":valueList",      qVariantFromValue(valueList));

     return execDBAction(action, parameters);
diff --git a/libs/database/core/databasecorebackend.h b/libs/database/core/databasecorebackend.h
index fa4dba4..ea8d558 100644
--- a/libs/database/core/databasecorebackend.h
+++ b/libs/database/core/databasecorebackend.h
@@ -42,15 +42,12 @@
 namespace Digikam
 {

-class ThumbnailSchemaUpdater;
-class DatabaseErrorHandler;
 class DatabaseCoreBackendPrivate;
-
-// ------------------------------------------------------------------------------------------------------------
+class DatabaseErrorHandler;
+class ThumbnailSchemaUpdater;

 class DIGIKAM_EXPORT DatabaseLocking
 {
-
 public:

     DatabaseLocking();
@@ -61,7 +58,7 @@ public:
     int    lockCount;
 };

-// ------------------------------------------------------------------------------------------------------------
+// -----------------------------------------------------------------

 class DIGIKAM_EXPORT DatabaseCoreBackend : public QObject
 {
@@ -202,7 +199,7 @@ public:
      * Add a DatabaseErrorHandler. This object must be created in the main thread.
      * If a database error occurs, this object can handle problem solving and user interaction.
      */
-    void setDatabaseErrorHandler(DatabaseErrorHandler* handler);
+    void setDatabaseErrorHandler(DatabaseErrorHandler* const handler);

     /**
       * Return config read from XML,
@@ -265,10 +262,10 @@ public:
      * Executes the SQL statement, and write the returned data into the values list.
      * If you are not interested in the returned data, set values to 0.
      * Methods are provided for up to four bound values (positional binding), or for a list of bound values.
-     * If you want the last inserted id (and your query is suitable), sett lastInsertId to the address of a QVariant.
+     * If you want the last inserted id (and your query is suitable), set lastInsertId to the address of a QVariant.
      * Additionally, methods are provided for prepared statements.
      */
-    QueryState execSql(const QString& sql, QList<QVariant>* values = 0, QVariant* const lastInsertId = 0);
+    QueryState execSql(const QString& sql, QList<QVariant>* const values = 0, QVariant* const lastInsertId = 0);
     QueryState execSql(const QString& sql, const QVariant& boundValue1,
                        QList<QVariant>* const values = 0, QVariant* const lastInsertId = 0);
     QueryState execSql(const QString& sql,
diff --git a/libs/database/core/databasecorebackend_p.h b/libs/database/core/databasecorebackend_p.h
index ff3a3fa..1f60dd7 100644
--- a/libs/database/core/databasecorebackend_p.h
+++ b/libs/database/core/databasecorebackend_p.h
@@ -75,7 +75,6 @@ public:
     void closeDatabaseForThread();
     bool incrementTransactionCount();
     bool decrementTransactionCount();
-    bool isInTransactionInOtherThread() const;

     bool isInMainThread() const;
     bool isInUIThread()   const;
@@ -145,10 +144,10 @@ public :
         DatabaseCoreBackendPrivate* const d;
     };

-    // ----------------------------------------------------------------------
-
     friend class AbstractUnlocker;

+    // ------------------------------------------------------------------
+
     class AbstractWaitingUnlocker : public AbstractUnlocker
     {
     public:
@@ -164,7 +163,7 @@ public :
         QWaitCondition* const condVar;
     };

-    // ----------------------------------------------------------------------
+    // ------------------------------------------------------------------

     class ErrorLocker : public AbstractWaitingUnlocker
     {
@@ -174,7 +173,7 @@ public :
         void wait();
     };

-    // ----------------------------------------------------------------------
+    // ------------------------------------------------------------------

     class BusyWaiter : public AbstractWaitingUnlocker
     {
Comment 33 caulier.gilles 2014-12-15 12:59:42 UTC
Next digiKam release 4.6.0 will include several important commits from Marcel to try to fix this memory leak with SQlite database

Gilles Caulier
Comment 34 Christoph Feck 2014-12-23 00:33:15 UTC
*** Bug 342144 has been marked as a duplicate of this bug. ***
Comment 35 Christian 2015-01-22 12:26:19 UTC
The problem is better in Digikam 4.6.0, but the issue remains. I am not sure about the details yet (still testing), but it seems to me that, most of the time, the following task works now:
* Change the name on a face with a name
However, I still get memory problems/crashes when I do the following:
* Assign an "Unidentified face" to an assisting name
* Remove face detection marks when they do not show a face.
I'm not sure which of these two is the problem in 4.6.0, but I think it's the face-name assignment.
Comment 36 Christian 2015-01-22 12:28:08 UTC
One thing that has definitely been improved in 4.6.0 is, that the digikam remembers everything that I do with the faces - even after the crash the modified information is still there. (In 4.4.0 it let me continue assign names and they were not saved any longer after a while.)
Comment 37 Christian 2015-01-23 14:09:09 UTC
I tried to run the "erase face recognition database and re-learn from the existing tags" command, but this also runs into an out-of-memory error after using up all the available memory and swap. (Takes over an hour because it gets so slow with all the swapping...)

However, that command, the way I understand it, should not modify the tags from the SQL database. So maybe the crash on the "erase and relearn" command is an unrelated bug. Unfortunately I have no debug output because of the memory/swap issue.
Comment 38 Christian 2015-01-23 16:45:28 UTC
Another piece of this puzzle. In 4.6.0, the face tagging appears to work without any memory leaks or bugs when I tag the faces in the Album view. But when I tag them in the "Unidentified faces" view, then the memory leak occurs and eventually (after exhausting all the swap and memory) digikam crashes.
Maybe this has to do with some kind of race condition related to saving the changed face tag into the picture file and the picture being or not being any longer part of the "Unidentified faces" view?
Comment 39 caulier.gilles 2015-01-26 09:54:49 UTC
*** Bug 343314 has been marked as a duplicate of this bug. ***
Comment 40 Sreeram Boyapati 2015-02-26 18:49:08 UTC
@Christian, What do you mean by unidentified faces view?  

Is it People/Unknown in tags section. Where faces are detected but they are not recognized hence they are not given a tag?
Comment 41 caulier.gilles 2015-02-28 16:52:02 UTC
*** Bug 344661 has been marked as a duplicate of this bug. ***
Comment 42 caulier.gilles 2015-02-28 16:53:08 UTC
Proble also reported into bug#344661, with a valgrind trace of memory leak.

Gilles Caulier
Comment 43 wwdiver 2015-03-06 08:58:59 UTC
added a valgrind trace of memory leak.

Currently updated to digiKam version: 4:4.8.0-trusty~ppa1  (Philip Johnsson <philip.johnsson@gmail.com> PPA package) but same behaviour like described in bug#344661.
Comment 44 wwdiver 2015-03-06 09:01:05 UTC
Created attachment 91447 [details]
digikam valgrind memory leak trace
Comment 45 Johannes 2015-03-08 18:51:17 UTC
to comment #38:

here it crashes in all cases. If I try to give a face a name then eventually the memory leak occurs and (after exhausting all the swap and memory) digikam crashes.

it happends every time

here it is used:

opensude 13.1 
KDE 4.11.5
digiKam 4.7.0 (last version I can get on (openSUSE BuildService - KDE:Extra)
Comment 46 Johannes 2015-03-10 11:43:38 UTC
I got some updates and also to DigiKam 4.8.0 but still same crash:

give a name to face results in eating all memory and crash
it happends in file view and it happends in unknown people view
Comment 47 Johannes 2015-03-12 15:03:56 UTC
I tried to give some more informations, but it seems very difficuilt.

When starting DigiKam under gdm I get request to install some debug-info packages. I treid but most often I get message:
"zypper install -C "debuginfo(build-id)=05418c8b523e59cd43336b1f984b7410a49ecf4c"
Daten des Repositories laden ...
Installierte Pakete lesen ...
Keine Anbieter von 'debuginfo(build-id) = 05418c8b523e59cd43336b1f984b7410a49ecf4c' gefunden.
Paketabhängigkeiten auflösen ...

Keine auszuführenden Aktionen."

so there are no packages to install.

This list of needed packages is very, very long!

Is there a simple way to install all needed packages in one shot?

Johannes
Comment 48 Johannes 2015-03-18 10:26:12 UTC
Created attachment 91618 [details]
start of digikam 4.8.0 on opensuse 13.1

I hope this backtrace helps a little bit.

But with this I do not come to the crash, It only starts digikam but it is not usable.

in normal use (and also unde use of gdb) I do not get the crash screen of KDE, so what can I do to give more helpful informations?

Johannes
Comment 49 Maik Qualmann 2015-03-20 20:20:31 UTC
Created attachment 91657 [details]
libkface.patch

I put this patch ready for testing, he fixes a part of the problem. The memory leaks I can not reproduce, but the fast-growing "recognition.db" database. After starting digikam and a first assignment of unknown face, the entries in the table "OpenCV LBP Histograms" be doubled. So very quickly arise thousands of entries and digikam becomes very slow after the first assignment of an unknown face.

Maik
Comment 50 caulier.gilles 2015-03-21 13:59:11 UTC
Git commit 916b00af31981a0729e05a92ae212f05279e730f by Gilles Caulier.
Committed on 21/03/2015 at 13:57.
Pushed by cgilles into branch 'master'.

apply patch #91657 to fix libkface histogram DB table grawing at each registration of data.

M  +3    -0    libkface/recognition-opencv-lbph/lbphfacemodel.cpp

http://commits.kde.org/libkface/916b00af31981a0729e05a92ae212f05279e730f
Comment 51 caulier.gilles 2015-03-21 14:03:51 UTC
Git commit c2c45b7a025d65f9318037b27c0bf348d48db825 by Gilles Caulier.
Committed on 21/03/2015 at 14:02.
Pushed by cgilles into branch 'Applications/14.12'.

backport commit #916b00af31981a0729e05a92ae212f05279e730f from git/master to 14.12 branch

M  +3    -0    libkface/recognition-opencv-lbph/lbphfacemodel.cpp

http://commits.kde.org/libkface/c2c45b7a025d65f9318037b27c0bf348d48db825
Comment 52 caulier.gilles 2015-03-21 14:07:19 UTC
Git commit 0626017fb632e73549a86a6ba3a78d9569aa8768 by Gilles Caulier.
Committed on 21/03/2015 at 14:06.
Pushed by cgilles into branch 'Applications/15.04'.

backport commit #916b00af31981a0729e05a92ae212f05279e730f from git/master to 15.04 branch

M  +3    -0    libkface/recognition-opencv-lbph/lbphfacemodel.cpp

http://commits.kde.org/libkface/0626017fb632e73549a86a6ba3a78d9569aa8768
Comment 53 caulier.gilles 2015-03-21 14:34:51 UTC
Git commit 9239937e66ad091bef391781d1a17abb74961444 by Gilles Caulier.
Committed on 21/03/2015 at 14:32.
Pushed by cgilles into branch 'frameworks'.

backport commit #916b00af31981a0729e05a92ae212f05279e730f from git/master to
frameworks branch

M  +3    -0    src/recognition-opencv-lbph/lbphfacemodel.cpp

http://commits.kde.org/libkface/9239937e66ad091bef391781d1a17abb74961444
Comment 54 caulier.gilles 2015-03-21 14:37:58 UTC
To all users in this room :

I patched libkface with Maik patch everywhere in KDE git repositories.

I would to have a feedback about this patch to see if it's improve stability of face recognition.

Thanks in advance

Gilles Caulier
Comment 55 caulier.gilles 2015-03-21 14:43:32 UTC
*** Bug 345395 has been marked as a duplicate of this bug. ***
Comment 56 Stephan Olbrich 2015-03-21 19:01:11 UTC
I'm having the same problem or at least the memory-leak.
As soon as I use some face recognition feature, digikam fills the memory until what seems to be the limit for my 32bit system. I get no crash though.
I use the packages from ppa.launchpad.net/philip5/extra/ubuntu/

I managed to get a valgrind output. This is the last part, I'll attach the whole thing.
Unfortunatelly there are no debug-packages of libkface.

==12227== 1,110,977,532 bytes in 16,947 blocks are possibly lost in loss record 109,774 of 109,774
==12227==    at 0x402A17C: malloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==12227==    by 0x402C328: realloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==12227==    by 0x7158E5B: qRealloc(void*, unsigned int) (in /usr/lib/i386-linux-gnu/libQtCore.so.4.8.6)
==12227==    by 0x7162104: qUncompress(unsigned char const*, int) (in /usr/lib/i386-linux-gnu/libQtCore.so.4.8.6)
==12227==    by 0x591AE65: ??? (in /usr/lib/libkface.so.3.0.0)
==12227==    by 0x58EB14E: ??? (in /usr/lib/libkface.so.3.0.0)
==12227==    by 0x58DBB9C: KFaceIface::RecognitionDatabase::Private::train(KFaceIface::OpenCVLBPHFaceRecognizer*, QList<KFaceIface::Identity> const&, KFaceIface::TrainingDataProvider*, QString const&) (in /usr/lib/libkface.so.3.0.0)
==12227==    by 0x58DC33C: KFaceIface::RecognitionDatabase::train(QList<KFaceIface::Identity> const&, KFaceIface::TrainingDataProvider*, QString const&) (in /usr/lib/libkface.so.3.0.0)
==12227==    by 0x834EFE3: Digikam::Trainer::process(QExplicitlySharedDataPointer<Digikam::FacePipelineExtendedPackage>) (in /usr/bin/digikam)
==12227==    by 0x834F479: Digikam::Trainer::qt_static_metacall(QObject*, QMetaObject::Call, int, void**) (in /usr/bin/digikam)
==12227==    by 0x7282769: QMetaCallEvent::placeMetaCall(QObject*) (in /usr/lib/i386-linux-gnu/libQtCore.so.4.8.6)
==12227==    by 0x728A8C8: QObject::event(QEvent*) (in /usr/lib/i386-linux-gnu/libQtCore.so.4.8.6)
==12227== 
==12227== LEAK SUMMARY:
==12227==    definitely lost: 25,079 bytes in 108 blocks
==12227==    indirectly lost: 84,445 bytes in 4,975 blocks
==12227==      possibly lost: 1,194,355,851 bytes in 129,953 blocks
==12227==    still reachable: 273,164,475 bytes in 473,030 blocks
==12227==         suppressed: 0 bytes in 0 blocks
==12227== Reachable blocks (those to which a pointer was found) are not shown.
==12227== To see them, rerun with: --leak-check=full --show-leak-kinds=all
==12227== 
==12227== For counts of detected and suppressed errors, rerun with: -v
==12227== ERROR SUMMARY: 6206 errors from 5654 contexts (suppressed: 0 from 0)
Comment 57 Stephan Olbrich 2015-03-21 19:04:54 UTC
Created attachment 91667 [details]
valgrind output
Comment 58 Tobias Leupold 2015-03-24 11:36:01 UTC
I ran into the (probably) same problem using KPhotoAlbum: sometimes, training a face did last for 20 minutes or so with the recognition.db growing by > 100 MB (I recently wrote emails about this to you and Marcel, but I didn't find the cause).

With current git master (916b00a), this problem is not reproducible anymore with my "test" recognition.db I used to provoke this behavior. With libkface 14.12.2, I was able to do so each and every time.

Seems like it's fixed :-)
Comment 59 caulier.gilles 2015-03-24 13:05:40 UTC
Tobias,

Great to see this entry solved for you too. This confirm the fix.

Q : The face recognition DB growing is one problem. What's about the memory consumption on your computer while face recognition ? Did you seen a problem relevant of memory allocation not free at each commit in DB ?

Note : the memory is not leak. When host application is done, memory is free properly. It's just a run time problem (if it still exist)
Comment 60 Tobias Leupold 2015-03-24 18:30:04 UTC
At least, I did not notice an unusual memory usage. But I also did not search for it … could also be due to the different ways libkface is used in Digikam and KPA.
Comment 61 caulier.gilles 2015-03-24 19:00:17 UTC
Tobias,

In digiKam Face management is multi-threaded on multi-core CPU.

At least, did you use separated thread in KPhotoAlbum ?

Memory comsuption was visible on my computer when i process large collection. As i use 16Bb of RAM, i never crash digiKam (memory is never fully used).

Did you see a similar dysfunction on your computer ?

Gilles
Comment 62 Tobias Leupold 2015-03-24 22:56:18 UTC
I actually implemented multithreaded training processes, but those were unusable for our case because the recognition processes were mutexed by the training. So there was no benefit because the database was locked anyway.

The KPA workflow is apparently quite different from the Digikam workflow: it's Open image → detect faces → recognize faces → correct falsely detected faces by training them one by one → open next image → repeat.
Comment 63 caulier.gilles 2015-03-25 08:55:16 UTC
To end-users who report this file.

I think bug is fixed with current implementation from git/master (next 4.9.0)

I close this file now. Don't hesitate to re-open if necessary...

Gilles Caulier
Comment 64 Johannes 2015-04-09 08:56:42 UTC
new update of digikam 4.9.0 on a openSUSE 13.1

mark a face and name it -> all memory will eaten and crash of digikam but no crash KDE handler pops up, sorry.

I will try to run it with gdb but last time I was not able to install debug files

If it is really a Qt problem: what can I do to find out? What version will run properly? Maybe I have to update some other parts to get it run.
someone can dump a list of used parts (programs) to compare?

Johannes
Comment 65 caulier.gilles 2015-04-09 09:06:41 UTC
See last comment from this entry :

https://bugs.kde.org/show_bug.cgi?id=323888

Gilles Caulier
Comment 66 Johannes 2015-04-09 11:22:15 UTC
Thanks a lot, yes it works now.
Johannes
Comment 67 caulier.gilles 2015-04-12 13:48:51 UTC
*** Bug 346097 has been marked as a duplicate of this bug. ***
Comment 68 nadine 2015-07-22 22:02:45 UTC
Hi there,

got this problem with digikam 4.9, so I updated now to 4.11. But the problem is still there in 4.11.
This problem seems to be there for a long time now.
Is there are working patch for 4.11?

Greets,
Nadine
Comment 69 caulier.gilles 2015-07-22 22:25:48 UTC
Problem is fixed in libkface.

Gilles Caulier
Comment 70 nadine 2015-07-23 04:53:18 UTC
How can I get the libkface into tarball installation?
Comment 71 caulier.gilles 2015-07-23 05:05:35 UTC
libkface is released now with last stable KDE4
Comment 72 caulier.gilles 2015-07-23 21:55:49 UTC
*** Bug 350549 has been marked as a duplicate of this bug. ***
Comment 73 caulier.gilles 2015-10-18 10:40:03 UTC
*** Bug 353859 has been marked as a duplicate of this bug. ***
Comment 74 Ritesh Raj Sarraf 2015-10-20 13:30:42 UTC
Commenting here since my bug was duplicated to this bug.

Given the dependencies that digikam has, it would be much wiser for digikam to have an option (or in my opinion, have that as default) to restrict its consumption of memory to a defined limit.

For CPU and IO, it can be tricky. But please, for memory, you definitely can do that in-app. There is no good experience to the user, when by the system reports, it shows that digikam has eaten all your memory. Ideally this should have been intelligently handled by Linux, but until then, can you have something in the application itself ?

For most users: if you run into massive memory consumption, please try the following

prlimit --pid 26286 --rss=2465792000

In the above example the process ID of digikam is restricted memory to 2 GiB. And my face detection scan worked like a charm after that trick.
Comment 75 Ritesh Raj Sarraf 2015-10-20 13:32:47 UTC
@Gilles Caulier:

You mentioned fixed in libkface. Can you please specify the version?
I am currently on Digikam  with the bundled libraries and still see the problem.

digiKam version 4.13.0
CPU cores: 4
Demosaic GPL2 pack support: Unknown
Demosaic GPL3 pack support: Unknown
Exiv2 can write to Jp2: Yes
Exiv2 can write to Jpeg: Yes
Exiv2 can write to Pgf: Yes
Exiv2 can write to Png: Yes
Exiv2 can write to Tiff: Yes
Exiv2 supports XMP metadata: Yes
LibCImg: 130
LibEigen: 3.2.91
LibExiv2: 0.25
LibJPEG: 62
LibJasper: 1.900.1
LibKDE: 4.14.12
LibKExiv2: 2.4.0
LibKGeoMap support: no
LibKdcraw: 2.4.2
LibLCMS: 2060
LibLensFun: 0.2.8-0
LibLqr support: yes
LibPGF: 6.14.12
LibPNG: 1.2.50
LibQt: 4.8.7
LibRaw: 0.16.2
LibTIFF: LIBTIFF, Version 4.0.5 Copyright (c) 1988-1996 Sam Leffler Copyright (c) 1991-1996 Silicon Graphics, Inc.
Parallelized demosaicing: Unknown
RawSpeed codec support: Unknown
Baloo support: no
Database backend: QSQLITE
Kdepimlibs support: no
LibGphoto2: 2.5.8
LibKface: 3.5.0
LibKipi support: no
LibOpenCV: 2.4.9.1
Sqlite2 support: Yes
Comment 76 Peter 2016-09-05 08:32:53 UTC
This memory blow-out occurs during face tagging on my digikam 4.0 that came with Linux Mint 17.3 KDE and also on digikam 4.14 which I installed from philip5. The dodgy process fills swap memory quickly until it reaches the maximum crashing the program at that point. Shutting down the digikam GUI before this happens leaves a digikam process running until the memory limit is reached. I've read most of the above and the "RESOLVED FIXED" but it's very confusing. Can someone please give the solution in plain English?
Comment 77 Ritesh Raj Sarraf 2016-09-05 08:50:10 UTC
(In reply to Peter from comment #76)
> This memory blow-out occurs during face tagging on my digikam 4.0 that came
> with Linux Mint 17.3 KDE and also on digikam 4.14 which I installed from
> philip5. The dodgy process fills swap memory quickly until it reaches the
> maximum crashing the program at that point. Shutting down the digikam GUI
> before this happens leaves a digikam process running until the memory limit
> is reached. I've read most of the above and the "RESOLVED FIXED" but it's
> very confusing. Can someone please give the solution in plain English?

You should try out Digikam 5.x. I have not seen the issue on Digikam 5.
Comment 78 Peter 2016-09-05 22:31:20 UTC
Thank you for the prompt reply Ritesh.
The official repository has digikam 4.0. How do I get 5.x?

digikam.org advises tarball installation of 5.0 but "you run into all kinds of problems related to compiling". This sounds scary, but OK let's have a go:

> sudo apt-get remove digikam (removes v4.14)
> sudo apt-get build-dep digikam (no errors)
> sudo apt-get build-dep kipi-plugins (no errors)
> kf5-config --prefix (replies: command not found)
> bootstrap.linux (replies: This script require kf5-config CLI tool from KDE project but it's not installed.)
> sudo apt-get install kf5-config (replies: Unable to locate package kf5-config)
> kde4-config --prefix (replies: /usr)

... any suggestions how to install 5.0?
Comment 79 Andrew Goodbody 2016-09-06 07:25:44 UTC
Well Debian testing has 5.1.0, not sure how that relates to Mint. Also I though Philip had a ppa with 5.x in it, but I don't know that for sure. The build-dep will have only pulled in support for bulding digikam 4.x, unless you point at a repository with digikam 5.x in it. So you will need a whole bunch of kf5 dev packages.

# apt-file find kf5-config
libkf5kdelibs4support5-bin: /usr/bin/kf5-config
libkf5kdelibs4support5-bin: /usr/share/man/ca/man1/kf5-config.1.gz
libkf5kdelibs4support5-bin: /usr/share/man/de/man1/kf5-config.1.gz
libkf5kdelibs4support5-bin: /usr/share/man/it/man1/kf5-config.1.gz
libkf5kdelibs4support5-bin: /usr/share/man/man1/kf5-config.1.gz
libkf5kdelibs4support5-bin: /usr/share/man/nl/man1/kf5-config.1.gz
libkf5kdelibs4support5-bin: /usr/share/man/pt_BR/man1/kf5-config.1.gz
libkf5kdelibs4support5-bin: /usr/share/man/sv/man1/kf5-config.1.gz
libkf5kdelibs4support5-bin: /usr/share/man/uk/man1/kf5-config.1.gz
# apt-get install libkf5kdelibs4support5-bin
Comment 80 Peter 2016-09-22 05:05:01 UTC
In view of the deepening hassles, I gave up on digiKam 4.x. All versions that I tried crashed out on memory overflow during face detection as well as on face tagging as described above. 

So, installed Linux Mint 18 (which also came with a version 4 digiKam) and then got digiKam 5.1 from philip5/extras. Now face tagging works without the memory overflow, great! This is very exciting and I have high hopes that digiKam will be a very useful tool for managing my photo collection (when I learn to drive it properly).

Face detection by v5.1 works, mostly.  I've had a couple of crashes with face detection, but I haven't worked out the circumstances. I haven't tried face recognition, denoted as 'experimental'.