Как я могу вручную сбросить журнал наддува?

Я играю с Boost.Log в boost 1.54.0, чтобы увидеть, является ли это приемлемым вариантом для моего приложения. В общем, у меня нет проблем с буферизацией, поэтому я не собираюсь включать auto_flush или что-то еще … но я заметил, что сообщения, которые регистрируются перед вызовом fork() дублируются, и мне интересно, если это потому, что они буферизуются, буфер дублируется при копировании образа процесса, а затем оба процесса в конечном итоге записывают свои копии буфера в файл журнала …

Поэтому я хотел бы просто выполнить ручную очистку журнала, только один раз, непосредственно перед тем, как позвонить. fork() чтобы быть уверенным, что в памяти не осталось сообщений. Другими словами, я ищу что-то похожее на fflush(), .flush(), << flushи т. д., которые я могу использовать в журнале наддува.

Я пытался использовать << flush с журналом, но я все еще получаю дублированные сообщения, так что я не на 100% уверен, что он сбрасывается, и дубликаты вызваны какой-то другой проблемой, или он каким-то образом молча игнорирует << flush

Редактировать:

Я осмотрелся и обнаружил, что лог буста не безопасен для форка. Поэтому я должен добавить, что я не пытаясь использовать один и тот же журнал в родительском и дочернем процессах. У меня есть два сценария разветвления — в одном родительский объект немедленно завершает работу и дочерний контур (так что это должно быть безопасно), а в другом дочерний должен открыть свой отдельный файл журнала, так что это тоже должно быть безопасно … но я нужно выяснить, как близко приемник файла журнала, а затем открыть новый (в другом файле). Я полагаю, закрытие раковины также может быть способом заставить флеш …?

4

Решение

Ладно … Мне пришлось немного покопаться в буст-коде (но не слишком), и я обнаружил, что это работает:

Когда вы звоните add_file_log(strLogFilename) это возвращает shared_ptr<sink> где sink ваш тип раковины (например, shared_ptr< synchronous_sink< text_file_backend > >). Если вместо этого вы создаете свой приемник «вручную», то, конечно, у вас также есть указатель на него … Кажется, что оба приемника и бэкэнд имеют .flush() метод. Я не уверен, что вы напрямую получаете копию бэкэнда для вызова его сброса, но, похоже, сбрасывание на приемнике просто вызывает сброс его бэкэнда (ов), так что это работает. Вот пример кода того, что я нашел, чтобы работать для меня:

shared_ptr< synchronous_sink< text_file_backend > > pLogSink = add_file_log(strLogFilaname);
BOOST_LOG_TRIVIAL(debug) << "Boost log!";

// other work goes here

BOOST_LOG_TRIVIAL(debug) << "About to fork...";
if (pLogSink)
pLogSink->flush();
pid_t pid = fork();

if (pid < 0)
// handle error
else if (pid > 0)
exit(EXIT_SUCCESS); // parent terminates
assert(0 == pid); // child continues

BOOST_LOG_TRIVIAL(debug) << "Fork succeeded!";

Используя этот метод, теперь я вижу каждое сообщение журнала только один раз. Конечно, имейте в виду это предупреждение о смешивании Boost.Log с fork () …
http://boost-log.sourceforge.net/libs/log/doc/html/log/rationale/fork_support.html

В моем примере это безопасно только потому, что родительский процесс немедленно завершает работу после разветвления, вообще не касаясь журнала (после разветвления). Таким образом, нет никакого спора за журнал.

Несмотря на ограничения, я вижу использование этого в нескольких случаях: 1) демонизация процесса (что я и пытаюсь сделать здесь на самом деле), 2) шаблон fork-exec (который делает нормально работать с Boost.Log, согласно указанному выше URL), или 3) дочерний процесс немедленно закрывает приемник файлов и открывает новый приемник для журнала, который указывает на другой файл (из того, который использует родительский процесс) — I считать этот третий случай должен быть безопасным.

5

Другие решения

Еще более простой код (с тривиальной регистрацией):

#include <boost/filesystem.hpp>
#include <boost/log/core.hpp>
#include <boost/log/trivial.hpp>
#include <boost/log/sinks/text_file_backend.hpp>
#include <boost/log/utility/setup/file.hpp>

namespace logging = boost::log;

void InitLogging() {
boost::filesystem::path full_path(boost::filesystem::current_path());

auto sink = logging::add_file_log("sample.log");
BOOST_LOG_TRIVIAL(info) << "Log initialized.";
BOOST_LOG_TRIVIAL(info) << "Working dir: " << full_path;
sink->flush();
}

int main() {
InitLogging();
return 0;
}

Согласно моим тестам, флеш является методом блокировки. Я использую его только во время инициализации, поэтому, если там что-то не так, я знаю, где было выполнение.

4