mirror of
https://github.com/ZoneMinder/zoneminder.git
synced 2026-09-13 05:38:05 -04:00
SIGHUP means reload. zmc responds by closing its events, disconnecting the camera and reconnecting; the perl daemons respond by exiting so zmdc restarts them. zmdc.pl logrot hupped every managed process, so the nightly logrotate run cost about 8 seconds of capture on a default install. Rotating a log file only needs the daemon to drop its file handle, so use a separate signal for it. SIGWINCH is otherwise unused, is ignored by default and exists on every supported platform. - Logger (C++) installs a SIGWINCH handler beside its USR1/USR2 handler. The handler only sets a flag; the next logPrint closes the file and the write reopens it at the original path. This covers every C++ binary without touching any daemon's main loop. - Logger.pm registers WINCH alongside HUP in logSetSignal, which logInit already calls, so the scripts that install their own HUP handler still rotate. - zmdc.pl logrot sends WINCH. The logrotate config is unchanged - it still calls zmpkg.pl logrot. Filter.pm and FilterTerm.php justified MAX_EVENT_DAYS by events not outliving the nightly HUP, which is no longer what bounds them; cite SectionLength. Tests: tests/zm_logger_rotate.cpp and tests/perl/test_log_rotate_signal.pl both log, rename the file out from under the process, confirm writes still land in the renamed file, signal WINCH and confirm the original path is written again. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NDhTBPj9xEaT52pRmAufaP
69 lines
2.2 KiB
C++
69 lines
2.2 KiB
C++
/*
|
|
* This file is part of the ZoneMinder Project. See AUTHORS file for Copyright information
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify it
|
|
* under the terms of the GNU General Public License as published by the
|
|
* Free Software Foundation; either version 2 of the License, or (at your
|
|
* option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
* more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License along
|
|
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include "zm_catch2.h"
|
|
|
|
#include "zm_logger.h"
|
|
#include "zm_utils.h"
|
|
|
|
#include <csignal>
|
|
#include <cstdio>
|
|
#include <fstream>
|
|
#include <sstream>
|
|
#include <string>
|
|
#include <cstdlib>
|
|
#include <unistd.h>
|
|
|
|
static std::string slurp(const std::string &path) {
|
|
std::ifstream in(path);
|
|
std::stringstream ss;
|
|
ss << in.rdbuf();
|
|
return ss.str();
|
|
}
|
|
|
|
// logrotate renames the file and expects the daemon to let go of the old
|
|
// handle. SIGHUP does that but also means reload, which costs zmc a camera
|
|
// reconnect - see issue #5063 - so SIGWINCH is what logrotate reaches for.
|
|
TEST_CASE("SIGWINCH reopens the log file after rotation") {
|
|
std::string path = stringtf("/tmp/zm_test_logrot_%d.log", getpid());
|
|
std::string rotated = path + ".1";
|
|
unlink(path.c_str());
|
|
unlink(rotated.c_str());
|
|
|
|
setenv("LOG_FLUSH", "1", 1);
|
|
Logger::Options options(Logger::NOLOG, Logger::NOLOG, Logger::INFO, Logger::NOLOG);
|
|
options.mLogFile = path;
|
|
logInit("zm_test_logrot", options);
|
|
|
|
Info("before rotation");
|
|
REQUIRE(rename(path.c_str(), rotated.c_str()) == 0);
|
|
Info("still holding the old handle");
|
|
|
|
REQUIRE(slurp(rotated).find("still holding the old handle") != std::string::npos);
|
|
REQUIRE(slurp(path).empty());
|
|
|
|
raise(SIGWINCH);
|
|
Info("after rotation");
|
|
|
|
REQUIRE(slurp(path).find("after rotation") != std::string::npos);
|
|
REQUIRE(slurp(rotated).find("after rotation") == std::string::npos);
|
|
|
|
logTerm();
|
|
unlink(path.c_str());
|
|
unlink(rotated.c_str());
|
|
}
|