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
Add a new AUDIT logging level (-5) between PANIC (-4) and NOLOG (shifted
to -6) across C++, PHP, and Perl loggers. AUDIT entries use code 'AUD'
and syslog priority LOG_NOTICE. They record who changed what, from where,
for monitors, filters, users, config, roles, groups, zones, states,
servers, storage, events, snapshots, control caps, and login/logout.
AUDIT entries have their own retention period (ZM_LOG_AUDIT_DATABASE_LIMIT,
default 1 year) separate from regular log pruning. The log pruning in
zmstats.pl and zmaudit.pl now excludes AUDIT rows from regular pruning
and prunes them independently.
Critical safety: the C++ termination logic is changed from
'if (level <= FATAL)' to 'if (level == FATAL || level == PANIC)' to
prevent AUDIT-level log calls from killing the process.
Includes db migration zm_update-1.39.1.sql to shift any stored NOLOG
config values from -5 to -6.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
GCC 12 incorrectly detects a format truncation.
src/zm_logger.cpp:86:39: warning: ‘%d’ directive output may be truncated writing between 1 and 11 bytes into a region of size 2 [-Wformat-truncation=]
86 | snprintf(code, sizeof(code), "DB%d", i);
| ^~
src/zm_logger.cpp:86:36: note: directive argument in the range [-2147483647, 9]
86 | snprintf(code, sizeof(code), "DB%d", i);
| ^~~~~~
Unfortunately the compilers can't emit Wformat warnings for variadic templates
and those can't be annotated with the format attribute.
Use a variadic function which can be annotated and thus warns on format string-args mismatches.
Ref 0796a2262e
With this we can ensure that no copy-construction of the SQL string takes place.
Regarding calling semantics: The pushed SQL string will be moved and cannot be reused.
Since we are now multi-threaded it can happen quite easily that a log message should be written to the DB on one thread while the other thread executes another query. Don't bail out immediately in the logging code, instead try to obtain the lock within 1s.
Remove calls to zmDBConnect from various places to avoid possible side-effects/double initialization.
The function should be called once from the main thread of the daemon.
Also split config loading into 2 steps: static and DB config loading. Load the static config before zmDBConnect is called so it has a chance to succeed.
With this commit a unified structure for includes is introduced.
The general rules:
* Only include what you need
* Include wherever possible in the cpp and forward-declare in the header
The includes are sorted in a local to global fashion. This means for the include order:
0. If cpp file: The corresponding h file and an empty line
1. Includes from the project sorted alphabetically
2. System/library includes sorted alphabetically
3. Conditional includes