Fix doc and example of QLoggingCategory::installCategory()

Snippet [22] was unused and the example using snippet [21] neglected
to show how its oldCategoryFilter got initialized, which is what [22]
does. But it turns out the example code was crashy in any case, as it
left the oldCategoryFilter uninitialized (albeit probably null) until
the call to installFilter() had returned, and installFilter() calls
the new filter, so the new filter needs to check oldCategoryFilter
before calling it. The doc also failed to explain why it's OK to not
defer to the prior filter in these calls during installFilter(), so
revise the doc and example so that the latter behaves sensibly and
readers of the former are likely to use the function safely.

This amends commit 8f0654ceb878b6c8a08c7f5b790027c26e007c13 which
added the snippets and the use of one of them, but not the other.

Fixes: QTBUG-49704
Pick-to: 6.4 6.3 6.2 5.15
Change-Id: Iddb8d97b0bef417d8f16e7910730cfa59ea3e715
Reviewed-by: Kai Koehne <kai.koehne@qt.io>
This commit is contained in:
Edward Welbourne 2022-06-02 11:17:17 +02:00 committed by Kai Koehne
parent 1480588f44
commit 6ae2bfad41
2 changed files with 34 additions and 13 deletions

View File

@ -1,4 +1,4 @@
// Copyright (C) 2016 The Qt Company Ltd. // Copyright (C) 2022 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QCoreApplication> #include <QCoreApplication>
@ -39,15 +39,20 @@ void myCategoryFilter(QLoggingCategory *);
//![20] //![20]
//![21] //![21]
QLoggingCategory::CategoryFilter oldCategoryFilter; static QLoggingCategory::CategoryFilter oldCategoryFilter = nullptr;
void myCategoryFilter(QLoggingCategory *category) void myCategoryFilter(QLoggingCategory *category)
{ {
// configure driver.usb category here, otherwise forward to to default filter. // For a category set up after this filter is installed, we first set it up
// with the old filter. This ensures that any driver.usb logging configured
// by the user is kept, aside from the one level we override; and any new
// categories we're not interested in get configured by the old filter.
if (oldCategoryFilter)
oldCategoryFilter(category);
// Tweak driver.usb's logging, over-riding the default filter:
if (qstrcmp(category->categoryName(), "driver.usb") == 0) if (qstrcmp(category->categoryName(), "driver.usb") == 0)
category->setEnabled(QtDebugMsg, true); category->setEnabled(QtDebugMsg, true);
else
oldCategoryFilter(category);
} }
//![21] //![21]
@ -60,8 +65,6 @@ int main(int argc, char *argv[])
//![2] //![2]
//![22] //![22]
// ...
oldCategoryFilter = QLoggingCategory::installFilter(myCategoryFilter); oldCategoryFilter = QLoggingCategory::installFilter(myCategoryFilter);
//![22] //![22]

View File

@ -343,13 +343,27 @@ QLoggingCategory *QLoggingCategory::defaultCategory()
*/ */
/*! /*!
Installs a function \a filter that is used to determine which categories \brief Take control of how logging categories are configured.
and message types should be enabled. Returns a pointer to the previous
installed filter.
Every QLoggingCategory object created is passed to the filter, and the Installs a function \a filter that is used to determine which categories and
filter is free to change the respective category configuration with message types should be enabled. If \a filter is \nullptr, the default
\l setEnabled(). message filter is reinstated. Returns a pointer to the previously-installed
filter.
Every QLoggingCategory object that already exists is passed to the filter
before \c installFilter() returns, and the filter is free to change each
category's configuration with \l setEnabled(). Any category it doesn't
change will retain the configuration it was given by the prior filter, so
the new filter does not need to delegate to the prior filter during this
initial pass over existing categories.
Any new categories added later will be passed to the new filter; a filter
that only aims to tweak the configuration of a select few categories, rather
than completely overriding the logging policy, can first pass the new
category to the prior filter, to give it its standard configuration, and
then tweak that as desired, if it is one of the categories of specific
interest to the filter. The code that installs the new filter can record the
return from \c installFilter() for the filter to use in such later calls.
When you define your filter, note that it can be called from different threads; but never When you define your filter, note that it can be called from different threads; but never
concurrently. This filter cannot call any static functions from QLoggingCategory. concurrently. This filter cannot call any static functions from QLoggingCategory.
@ -357,6 +371,10 @@ QLoggingCategory *QLoggingCategory::defaultCategory()
Example: Example:
\snippet qloggingcategory/main.cpp 21 \snippet qloggingcategory/main.cpp 21
installed (in \c{main()}, for example) by
\snippet qloggingcategory/main.cpp 22
Alternatively, you can configure the default filter via \l setFilterRules(). Alternatively, you can configure the default filter via \l setFilterRules().
*/ */
QLoggingCategory::CategoryFilter QLoggingCategory::CategoryFilter