Безопасно ли добавлять или удалять приемники журналов, в то же время ведя журнал из других потоков с помощью журнала буста? - PullRequest
0 голосов
/ 09 апреля 2020

С boost :: log безопасно ли добавлять или удалять приемники журналов при ведении журнала из других потоков? Есть ли какая-то ручная блокировка, которую мне нужно сделать, чтобы сделать эти операции потокобезопасными?

Что я пытаюсь сделать, это запустить новый текстовый файл, который содержит подмножество записей существующего файла журнала между двумя точки в моей программе.

Например, если у меня есть следующие записи, идущие в файл журнала "main_debug.log"

line 1
line 2
line 3
line 4

И затем я добавляю новый приемник после строки 1, и удалите его после строки 3, я бы увидел «new_debug.log», содержащий следующие записи

line 2
line 3

То, что у меня, кажется, работает большую часть времени, но я иногда вижу ошибки сегментации, возникающие в boost :: журнал. Пример такого случая, когда мне удалось поймать его с помощью gdb:

Program received signal SIGSEGV, Segmentation fault.
[Switching to LWP 8760]
boost::intrusive::list_impl<boost::intrusive::derivation_value_traits<boost::log::v2_mt_posix::attribute_value_set::node, boost::log::v2_mt_posix::attribute_value_set::implementation::node_traits, (boost::intrusive::link_mode_type)0>, unsigned int, true, void>::clear_and_dispose<boost::log::v2_mt_posix::attribute_value_set::implementation::disposer> (this=0x5e64aff4, disposer=...) at /boost-1.60.0/boost/intrusive/list.hpp:738
738     /boost-1.60.0/boost/intrusive/list.hpp: No such file or directory.
(gdb) bt
#0  boost::intrusive::list_impl<boost::intrusive::derivation_value_traits<boost::log::v2_mt_posix::attribute_value_set::node, boost::log::v2_mt_posix::attribute_value_set::implementation::node_traits, (boost::intrusive::link_mode_type)0>, unsigned int, true, void>::clear_and_dispose<boost::log::v2_mt_posix::attribute_value_set::implementation::disposer> (this=0x5e64aff4, disposer=...) at /boost-1.60.0/boost/intrusive/list.hpp:738
#1  boost::log::v2_mt_posix::attribute_value_set::implementation::~implementation (this=0x5e64afe8, __in_chrg=<optimized out>) at /boost-1.60.0/libs/log/src/attribute_value_set.cpp:150
#2  boost::log::v2_mt_posix::attribute_value_set::implementation::destroy (p=0x5e64afe8) at /boost-1.60.0/libs/log/src/attribute_value_set.cpp:239
#3  boost::log::v2_mt_posix::attribute_value_set::~attribute_value_set (this=0x5e64b3e4, __in_chrg=<optimized out>) at /boost-1.60.0/libs/log/src/attribute_value_set.cpp:519
#4  0x76e3bbac in boost::log::v2_mt_posix::record_view::public_data::~public_data (this=0x5e64b3e0, __in_chrg=<optimized out>) at /boost-1.60.0/boost/log/core/record_view.hpp:86
#5  boost::log::v2_mt_posix::record_view::private_data::~private_data (this=0x5e64b3e0, __in_chrg=<optimized out>) at /boost-1.60.0/libs/log/src/core.cpp:79
#6  boost::log::v2_mt_posix::record_view::private_data::destroy (this=0x5e64b3e0) at /boost-1.60.0/libs/log/src/core.cpp:131
#7  boost::log::v2_mt_posix::record_view::public_data::destroy (p=0x5e64b3e0) at /boost-1.60.0/libs/log/src/core.cpp:184
#8  0x0020b030 in boost::log::v2_mt_posix::sinks::asynchronous_sink<boost::log::v2_mt_posix::sinks::text_file_backend, boost::log::v2_mt_posix::sinks::unbounded_fifo_queue>::run() ()
#9  0x76d4be6c in boost::(anonymous namespace)::thread_proxy (param=<optimized out>) at /boost-1.60.0/libs/thread/src/pthread/thread.cpp:167
#10 0x76c22f00 in ?? () from /lib/libpthread.so.0

Чтобы добавить новый приемник, я делаю следующее:

const auto pDebugBackend = boost::make_shared<boost::log::sinks::text_file_backend>(
    boost::log::keywords::file_name = "debug.log",
    boost::log::keywords::channel = "InfoConsole" );
const auto pNewDebugSink = boost::make_shared<boost::log::sinks::asynchronous_sink<boost::log::sinks::text_file_backend>>( pDebugBackend );

// Other code to set the filter and formatter for the sink.

boost::log::core::get()->add_sink( pNewDebugSink );

И для удаления некоторое время спустя у меня есть, что соответствует порядку, описанному в https://www.boost.org/doc/libs/1_60_0/libs/log/doc/html/log/detailed/sink_frontends.html#log .detailed.sink_frontends.asyn c:

boost::log::core::get()->remove_sink( pNewDebugSink );
pNewDebugSink->stop();
pNewDebugSink->flush();
pNewDebugSink.reset();

Я использую Boost-1.60.0, и он построен с включенной поддержкой потоков.

1 Ответ

1 голос
/ 09 апреля 2020

С boost :: log безопасно ли добавлять или удалять приемники журналов при ведении журнала из других потоков?

Да, хотя добавление и удаление приемников - это две разные операции, и вы может пропустить некоторые записи журнала, пока старый приемник удален, а новый еще не добавлен.

Что касается сбоев, которые вы видите, то это происходит, когда выделенный поток ведения журнала все еще работает (т.е. до stop метод завершен), поэтому возможно, что удаление раковины не связано. Это может быть ошибка в Boost.Log или какой-либо другой используемой им библиотеке, но ваша версия Boost довольно старая. Попробуйте обновить и, если он все еще воспроизводится, сообщить об ошибке в Boost.Log с примером кода для воспроизведения.

...