suricata
log-maintenance.c
Go to the documentation of this file.
1 /* Copyright (C) 2026 Open Information Security Foundation
2  *
3  * You can copy, redistribute or modify this Program under the terms of
4  * the GNU General Public License version 2 as published by the Free
5  * Software Foundation.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * version 2 along with this program; if not, write to the Free Software
14  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15  * 02110-1301, USA.
16  */
17 
18 /**
19  * \file
20  *
21  * \author Jeff Lucovsky <jlucovsky@oisf.net>
22  */
23 
24 #include "suricata-common.h"
25 #include "suricata.h"
26 #include "log-maintenance.h"
27 #include "util-logopenfile.h"
28 #include "tm-threads.h"
29 #include "conf.h"
30 #include "conf-yaml-loader.h"
31 #include "util-privs.h"
32 
34 {
35  intmax_t output_flush_interval = 0;
36  if (SCConfGetInt("heartbeat.output-flush-interval", &output_flush_interval) == 0) {
37  output_flush_interval = 0;
38  }
39  if (output_flush_interval < 0 || output_flush_interval > 60) {
40  SCLogConfig("flush_interval must be 0 or less than 60; using 0");
41  output_flush_interval = 0;
42  }
43 
44  return (int)output_flush_interval;
45 }
46 
47 static void *LogMaintenanceThread(void *arg)
48 {
49  int output_flush_interval = OutputFlushInterval();
50 
51  if (output_flush_interval > 0) {
52  SCLogConfig("Log maintenance thread started: rotation check every 1s, flush interval %ds",
53  output_flush_interval);
54  } else {
55  SCLogConfig("Log maintenance thread started: rotation check every 1s, flush disabled");
56  }
57 
58  /*
59  * Calculate the number of sleep intervals based on the output flush interval. This is necessary
60  * because this thread pauses a fixed amount of time to react to shutdown situations more
61  * quickly.
62  */
63  const int maintenance_sleep_time = 500; /* milliseconds */
64  const int rotation_wait_count = 1000 / maintenance_sleep_time; /* = 2, check every 1 second */
65  const int flush_wait_count =
66  output_flush_interval > 0 ? (1000 * output_flush_interval) / maintenance_sleep_time : 0;
67 
68  ThreadVars *tv_local = (ThreadVars *)arg;
69  SCSetThreadName(tv_local->name);
70 
71  if (tv_local->thread_setup_flags != 0)
72  TmThreadSetupOptions(tv_local);
73 
74  /* Set the threads capability */
75  tv_local->cap_flags = 0;
76  SCDropCaps(tv_local);
77 
79 
80  int rotation_counter = 0;
81  int flush_counter = 0;
82  uint64_t rotation_check_count = 0;
83  uint64_t worker_flush_count = 0;
84  bool completed_slice = false;
85  bool run = TmThreadsWaitForUnpause(tv_local);
86  while (run) {
87  /* killed before completing the first slice: skip it - the fixed
88  * sleep would only delay shutdown, no rotation or flush can
89  * happen on this pass. A kill arriving later keeps the normal
90  * behaviour: the current slice still runs its rotation/flush. */
91  if (!completed_slice && TmThreadsCheckFlag(tv_local, THV_KILL)) {
92  break;
93  }
94 
95  SleepMsec(maintenance_sleep_time);
96 
97  /* Check rotation every 1 second */
98  if (++rotation_counter >= rotation_wait_count) {
99  rotation_check_count++;
101  rotation_counter = 0;
102  }
103 
104  /* Flush at configured interval (if enabled) */
105  if (flush_wait_count > 0 && ++flush_counter >= flush_wait_count) {
106  worker_flush_count++;
107  LogFileFlushAll();
108  flush_counter = 0;
109  }
110 
111  completed_slice = true;
112 
113  if (TmThreadsCheckFlag(tv_local, THV_KILL)) {
114  break;
115  }
116  }
117 
119  TmThreadWaitForFlag(tv_local, THV_DEINIT);
120  TmThreadsSetFlag(tv_local, THV_CLOSED);
121  SCLogInfo("%s: performed %" PRIu64 " rotation checks, %" PRIu64 " flushes", tv_local->name,
122  rotation_check_count, worker_flush_count);
123  return NULL;
124 }
125 
127 {
128  ThreadVars *tv_maintenance =
129  TmThreadCreateMgmtThread(thread_name_heartbeat, LogMaintenanceThread, 1);
130  if (!tv_maintenance || (TmThreadSpawn(tv_maintenance) != 0)) {
131  FatalError("Unable to create and start log maintenance thread");
132  }
133 }
tm-threads.h
TmThreadSpawn
TmEcode TmThreadSpawn(ThreadVars *tv)
Spawns a thread associated with the ThreadVars instance tv.
Definition: tm-threads.c:1710
TmThreadSetupOptions
TmEcode TmThreadSetupOptions(ThreadVars *tv)
Set the thread options (cpu affinitythread). Priority should be already set by pthread_create.
Definition: tm-threads.c:873
LogMaintenanceThreadSpawn
void LogMaintenanceThreadSpawn(void)
Definition: log-maintenance.c:126
LogFileRotateAll
void LogFileRotateAll(void)
Check rotation for all registered LogFileCtx instances.
Definition: util-logopenfile.c:1105
TmThreadsSetFlag
void TmThreadsSetFlag(ThreadVars *tv, uint32_t flag)
Set a thread flag.
Definition: tm-threads.c:102
TmThreadWaitForFlag
void TmThreadWaitForFlag(ThreadVars *tv, uint32_t flags)
Waits till the specified flag(s) is(are) set. We don't bother if the kill flag has been set or not on...
Definition: tm-threads.c:1830
THV_DEINIT
#define THV_DEINIT
Definition: threadvars.h:44
SCSetThreadName
#define SCSetThreadName(n)
Definition: threads.h:305
THV_RUNNING
#define THV_RUNNING
Definition: threadvars.h:54
util-privs.h
SCDropCaps
#define SCDropCaps(...)
Definition: util-privs.h:89
OutputFlushInterval
int OutputFlushInterval(void)
Definition: log-maintenance.c:33
THV_RUNNING_DONE
#define THV_RUNNING_DONE
Definition: threadvars.h:45
log-maintenance.h
SCConfGetInt
int SCConfGetInt(const char *name, intmax_t *val)
Retrieve a configuration value as an integer.
Definition: conf.c:440
ThreadVars_
Per thread variable structure.
Definition: threadvars.h:57
THV_KILL
#define THV_KILL
Definition: threadvars.h:39
LogFileFlushAll
void LogFileFlushAll(void)
Flush all registered LogFileCtx instances.
Definition: util-logopenfile.c:1087
conf-yaml-loader.h
conf.h
TmThreadCreateMgmtThread
ThreadVars * TmThreadCreateMgmtThread(const char *name, void *(fn_p)(void *), int mucond)
Creates and returns the TV instance for a Management thread(MGMT). This function supports only custom...
Definition: tm-threads.c:1103
SCLogInfo
#define SCLogInfo(...)
Macro used to log INFORMATIONAL messages.
Definition: util-debug.h:232
THV_INIT_DONE
#define THV_INIT_DONE
Definition: threadvars.h:36
SleepMsec
#define SleepMsec(msec)
Definition: tm-threads.h:45
suricata-common.h
thread_name_heartbeat
const char * thread_name_heartbeat
Definition: runmodes.c:76
TmThreadsWaitForUnpause
bool TmThreadsWaitForUnpause(ThreadVars *tv)
Wait for a thread to become unpaused.
Definition: tm-threads.c:371
FatalError
#define FatalError(...)
Definition: util-debug.h:517
SCLogConfig
struct SCLogConfig_ SCLogConfig
Holds the config state used by the logging api.
util-logopenfile.h
suricata.h
TmThreadsCheckFlag
int TmThreadsCheckFlag(ThreadVars *tv, uint32_t flag)
Check if a thread flag is set.
Definition: tm-threads.c:94
THV_CLOSED
#define THV_CLOSED
Definition: threadvars.h:41