Currently, we build Krita for our users with HIDE_SAFE_ASSERTS=ON. To our users, hitting a KIS_*_ASSERT that means a crash. The assert message itself is added to the logfile.
Currently, if we would build Krita with HIDE_SAFE_ASSERTS=OFF, the users would see a scary message box warning them Krita is about to crash, with ignore and abort buttons. Abort promises more information, but doesn't give that information except on platforms with drkonqui running.
Definitions:
- Q_ASSERT: a real assert, of the type that checks whether something is like the developer thought, aborts Krita in a developer build and is compiled out in a release build because the developer knows the problem isn't so bad the application halts
- KIS_*_ASSERT: a family of "fake" asserts, that right now either shows a message box, shows a warning or throws an exception caught by KisApplication.
Now that we have millions of users, we want to:
- Not scare our very untechnical users
- Not make our users lose data unnecessarily:
- no qFatal until the user has had a chance to save the file
- or autosave all files on hitting an assert and then abort?
- Not abort if it isn't really necessary.
- Gather useful information for bug reports
- Make development easier by having asserts abort Krita during development
For that we need to reimagine the way our error detection and recovery works.
- Asserts need to be logged, with a full backtrace
- We need to review all KIS*ASSERTS and Q_ASSERTS to see which ones should be converted to KIS_SAFE*ASSERTS.
- Saving code should never be able to hit any assert
- Asserts that claim to be recoverable should recover, as gracefully as possible, except in developer builds
- Asserts that cannot recover should autosave and restart krita, except in developer builds
- We need a system to distinguish between developer builds and release builds
- developer builds should halt
- release builds should show a message in the system log
- We need a system to distinguish between alpha/beta builds and final release builds
- Alpha/beta builds should have a message box that shows the assert and presents an easy way to report the bug, including the backtrace (kisBacktrace)
- Release builds should act to save the user's data, then tell the user that Krita will restart and that any data can be recovered.
Related Notes
- We assume that qCritical aborts. It doesn't, but we say so in the error messages.
- KoImageCollection has an abort() call
- bspline_create.cpp has many abort() calls
- kxmlguiclient.cpp has an abort() call
- We have 63 qFatal calls.
- Q_ASSERT is only compiled in Debug mode, not RelWithDebInfo, which we use for our release builds.
- KIS_*_ASSERT is always built, in Debug RelWithDebInfo and Release mode
Better Bug Reports
Asserts that show information to the user should use KBugReport. We want to extend KBugReport using the REST api of bugzilla (https://bugzilla.readthedocs.io/en/5.0/api/core/v1/bug.html#create-bug).
It would be very useful to add the system info file, the system log and the crash log (on Windows) as attachments or comments to bug reports created with kbugreport. For this, we need permission from sysadmin.
- kisBacktrace is dependent on there being a function present called backtrace? On Linux, this is true with Release builds as well. On macOS this is true with RelWithDebInfo.
Also: only on Linux do we have drkonqui. On macOS we have nothing, and on Windows we have a kritacrash.log with (bad) backtraces and a krita.log which contains the last backtrace from kritacrash.log after ending with an error.
Saving The Data
kis_assert.cpp says:
/** * TODO: Add automatic saving of the documents * * Requirements: * 1) Should save all open KisDocument objects * 2) Should *not* overwrite original document since the saving * process may fail. * 3) Should *not* overwrite any autosaved documents since the saving * process may fail. * 4) Double-fault tolerance! Assert during emergency saving should not * lead to an infinite loop. */
But actually, saving the document should be save; the last save is in the backup document, and copying the new version over the old is atomic, these days.