#include "hash/hash_defs.h"
#include "hash/zhash.h"
#include "helpers/flag_context.h"
+#include "main/thread_config.h"
#include "packet_io/active.h"
#include "packet_tracer/packet_tracer.h"
#include "stream/base/stream_module.h"
static const unsigned ALLOWED_FLOWS_ONLY = 1;
static const unsigned OFFLOADED_FLOWS_TOO = 2;
static const unsigned ALL_FLOWS = 3;
+static const unsigned WDT_MASK = 7; // kick watchdog once for every 8 flows deleted
//-------------------------------------------------------------------------
// FlowCache stuff
continue;
}
- // we have a winner...
+ if ( (deleted & WDT_MASK) == 0 )
+ ThreadConfig::preemptive_kick();
+
unlink_uni(flow);
if ( flow->was_blocked() )
// delete from the free list first...
while ( num_to_delete )
{
+ if ( (deleted & WDT_MASK) == 0 )
+ ThreadConfig::preemptive_kick();
+
Flow* flow = (Flow*)hash_table->pop();
if ( !flow )
break;
#include "flow/session.h"
#include "main/policy.h"
#include "main/snort_config.h"
+#include "main/thread_config.h"
#include "managers/inspector_manager.h"
#include "packet_io/active.h"
#include "packet_tracer/packet_tracer.h"
void snort::trace_vprintf(const char*, TraceLevel, const char*, const Packet*, const char*, va_list) {}
uint8_t snort::TraceApi::get_constraints_generation() { return 0; }
void snort::TraceApi::filter(const Packet&) {}
+void ThreadConfig::preemptive_kick() {}
namespace snort
{
class WatchdogKick : public AnalyzerCommand
{
public:
- WatchdogKick(Watchdog* d) : dog(d) { dog->waiting = true; }
+ WatchdogKick(Watchdog* d) : dog(d) { }
bool execute(Analyzer&, void**) override
{
dog->resp[get_instance_id()] = true;
}
const char* stringify() override { return "WATCHDOG_KICK"; }
- ~WatchdogKick() override { dog->waiting = false; }
+ ~WatchdogKick() override { }
private:
Watchdog* dog;
};
if ( waiting )
{
uint16_t thread_count = 0;
- WarningMessage("Packet processing threads are unresponsive\n");
- WarningMessage("Unresponsive thread ID: ");
for ( unsigned i = 0; i < max; ++i )
{
if ( !resp[i] )
{
++thread_count;
+ if (thread_count == 1)
+ {
+ WarningMessage("Packet processing threads are unresponsive\n");
+ WarningMessage("Unresponsive thread ID: ");
+ }
const int tid = SnortConfig::get_conf()->thread_config->get_instance_tid(i);
if ( tid != -1 )
WarningMessage("%d (TID: %d)", i, tid);
WarningMessage("%d ", i);
}
}
- WarningMessage("\n");
+
+ if ( thread_count )
+ WarningMessage("\n");
+
if ( thread_count >= SnortConfig::get_conf()->watchdog_min_thread_count )
{
WarningMessage("Aborting Snort\n");
resp[i] = false;
main_broadcast_command(new WatchdogKick(this), nullptr);
+ waiting = true;
}
-static void s_watchdog_handler(void*)
+static Watchdog& get_watchdog()
{
static Watchdog s_dog(SnortConfig::get_conf()->watchdog_timer);
+ return s_dog;
+}
+
+static void s_watchdog_handler(void*)
+{
+ Watchdog& dog = get_watchdog();
if ( SnortConfig::get_conf()->watchdog_timer > 0 )
{
- if ( s_dog.seconds_count > 0 )
- s_dog.seconds_count--;
+ if ( dog.seconds_count > 0 )
+ dog.seconds_count--;
else
{
- s_dog.kick();
- s_dog.seconds_count = SnortConfig::get_conf()->watchdog_timer;
+ dog.kick();
+ dog.seconds_count = SnortConfig::get_conf()->watchdog_timer;
}
}
}
Periodic::register_handler(s_watchdog_handler, nullptr, 0, 1000);
}
+void ThreadConfig::preemptive_kick()
+{
+ if (SnortConfig::get_conf()->watchdog_timer)
+ {
+ Watchdog& dog = get_watchdog();
+ dog.resp[get_instance_id()] = true;
+ }
+}
+
// -----------------------------------------------------------------------------
// unit tests