Skip to content

Commit 2fc4e79

Browse files
committed
#384 add ability to cap off parallel hook processes
1 parent 5d183ae commit 2fc4e79

File tree

2 files changed

+56
-5
lines changed

2 files changed

+56
-5
lines changed

zmeventnotification.ini

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,23 @@ use_hooks = yes
229229

230230
# NOTE: This entire section is only valid if use_hooks is yes above
231231

232+
# When a hook is invoked, the ES forks a child. If you are in a situation
233+
# where your motion sensititivy in ZM is not set properly, you may land up
234+
# triggering hundreds of child processes of zm_detect that may potentially
235+
# crash your system. Note that there are global locks around the ML code which
236+
# are controlled by xxx_max_processes in the objectconfig/mlapiconfig.files
237+
# which will avoid parallel running of models. But this is if you are facing issues
238+
# by the simple fact that too many zm_detect processes are forked (which will apply
239+
# whether you use mlapi or not). While I do feel the core issue is that you need
240+
# to fix your ZM sensitivity, this parameter helps control.
241+
242+
# NOTE: When you put in value for this, any hooks that attempt to kick off
243+
# beyond this limit will simply be ignored. There is no queueing.
244+
245+
# A value of 0 (default) means there are no limits
246+
max_parallel_hooks=0
247+
248+
232249
# Shell script name here to be called every time an alarm is detected
233250
# the script will get passed $1=alarmEventID, $2=alarmMonitorId
234251
# $3 monitor Name, $4 alarm cause

zmeventnotification.pl

Lines changed: 39 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,9 @@
138138
'/var/lib/zmeventnotification/misc/escontrol_interface.dat',
139139
DEFAULT_FCM_DATE_FORMAT => '%I:%M %p, %d-%b',
140140
DEFAULT_FCM_ANDROID_PRIORITY=>'high',
141-
DEFAULT_MAX_FCM_PER_MONTH_PER_TOKEN => 8000
141+
DEFAULT_MAX_FCM_PER_MONTH_PER_TOKEN => 8000,
142+
143+
DEFAULT_MAX_PARALLEL_HOOKS => 0,
142144
};
143145

144146
# connection state
@@ -173,6 +175,7 @@
173175
my $es_terminate = 0;
174176

175177
my $child_forks = 0; # Global tracker of active children
178+
my $parallel_hooks = 0; # Global tracker for active hooks
176179
my $total_forks = 0; # Global tracker of all forks since start
177180

178181
# Declare options.
@@ -279,6 +282,8 @@
279282

280283
my %fcm_tokens_map;
281284

285+
my $max_parallel_hooks= 0;
286+
282287
my %monitors = ();
283288
my %active_events = ();
284289
my $monitor_reload_time = 0;
@@ -696,6 +701,12 @@ sub loadEsConfigSettings {
696701
DEFAULT_EVENT_END_NOTIFY_ON_HOOK_SUCCESS
697702
);
698703

704+
$max_parallel_hooks = config_get_val(
705+
$config, 'hook',
706+
'max_parallel_hooks',
707+
DEFAULT_MAX_PARALLEL_HOOKS
708+
);
709+
699710
# get channels and convert to hash
700711

701712
%event_start_notify_on_hook_fail = map { $_ => 1 }
@@ -807,10 +818,11 @@ sub print_config {
807818
Monitor rules JSON file................${\(value_or_undefined($es_rules_file))}
808819
809820
Use Hooks............................. ${\(yes_or_no($use_hooks))}
821+
Max Parallel Hooks.................... ${\(value_or_undefined($max_parallel_hooks))}
810822
Hook Script on Event Start ........... ${\(value_or_undefined($event_start_hook))}
811823
User Script on Event Start.............${\(value_or_undefined($event_start_hook_notify_userscript))}
812824
Hook Script on Event End.............. ${\(value_or_undefined($event_end_hook))}
813-
User Script on Event End.............${\(value_or_undefined($event_end_hook_notify_userscript))}
825+
User Script on Event End...............${\(value_or_undefined($event_end_hook_notify_userscript))}
814826
Hook Skipped monitors................. ${\(value_or_undefined($hook_skip_monitors))}
815827
816828
Notify on Event Start (hook success).. ${\(value_or_undefined($event_start_notify_on_hook_success))}
@@ -2374,6 +2386,17 @@ sub processJobs {
23742386
delete( $active_events{$mid}->{$eid} );
23752387
$child_forks--;
23762388
}
2389+
elsif ( $job eq 'update_parallel_hooks' ) {
2390+
if ($msg eq "add") {
2391+
$parallel_hooks++;
2392+
}
2393+
elsif ($msg eq "del") {
2394+
$parallel_hooks--;
2395+
}
2396+
else {
2397+
printError ("Parallel hooks update: command not understood: $msg");
2398+
}
2399+
}
23772400
elsif ( $job eq 'mqtt_publish' ) {
23782401
my ( $id, $topic, $payload ) = split( '--SPLIT--', $msg );
23792402
printDebug( "Job: MQTT Publish on topic: $topic", 2 );
@@ -3861,7 +3884,10 @@ sub processNewAlarmsInFork {
38613884
if ( $cmd =~ /^(.*)$/ ) {
38623885
$cmd = $1;
38633886
}
3887+
print WRITER "update_parallel_hooks--TYPE--add\n";
38643888
my $res = `$cmd`;
3889+
print WRITER "update_parallel_hooks--TYPE--del\n";
3890+
38653891
chomp($res);
38663892
my ( $resTxt, $resJsonString ) = parseDetectResults($res);
38673893
$hookResult = $? >> 8;
@@ -4093,7 +4119,11 @@ sub processNewAlarmsInFork {
40934119
if ( $cmd =~ /^(.*)$/ ) {
40944120
$cmd = $1;
40954121
}
4122+
4123+
print WRITER "update_parallel_hooks--TYPE--add\n";
40964124
my $res = `$cmd`;
4125+
print WRITER "update_parallel_hooks--TYPE--del\n";
4126+
40974127
chomp($res);
40984128
my ( $resTxt, $resJsonString ) = parseDetectResults($res);
40994129
$hookResult = $? >> 8;
@@ -4420,7 +4450,7 @@ sub initSocketServer {
44204450
exit(0);
44214451
}
44224452
my $elapsed_time_min = ceil((time() - $es_start_time)/60);
4423-
printDebug( "----------> Tick START (active forks:$child_forks, total forks:$total_forks, running for:$elapsed_time_min min)<--------------", 2 );
4453+
printDebug( "----------> Tick START (active forks:$child_forks, total forks:$total_forks, active hooks: $parallel_hooks running for:$elapsed_time_min min)<--------------", 2 );
44244454
if ( $restart_interval
44254455
&& ( ( time() - $es_start_time ) > $restart_interval ) )
44264456
{
@@ -4446,7 +4476,7 @@ sub initSocketServer {
44464476
checkConnection();
44474477
processJobs();
44484478

4449-
printDebug( "There are $child_forks active child forks...", 2 );
4479+
printDebug( "There are $child_forks active child forks & $parallel_hooks zm_detect processes running...", 2 );
44504480
my (@newEvents) = checkNewEvents();
44514481

44524482
#print Dumper(\@newEvents);
@@ -4468,6 +4498,10 @@ sub initSocketServer {
44684498
}
44694499

44704500
foreach (@newEvents) {
4501+
if (($parallel_hooks >= $max_parallel_hooks) && ($max_parallel_hooks != 0)) {
4502+
printError("There are $parallel_hooks hooks running as of now. This exceeds your set limit of max_parallel_hooks=$max_parallel_hooks. Ignoring this event. Either increase your max_parallel_hooks value, or, adjust your ZM motion sensitivity ");
4503+
return;
4504+
}
44714505
$child_forks++;
44724506
$total_forks++;
44734507
if ($cpid = fork() ) {
@@ -4523,7 +4557,7 @@ sub initSocketServer {
45234557
}
45244558

45254559
check_for_duplicate_token();
4526-
printDebug( "---------->Tick END (active forks:$child_forks, total forks:$total_forks)<--------------", 2 );
4560+
printDebug( "---------->Tick END (active forks:$child_forks, total forks:$total_forks, active hooks: $parallel_hooks)<--------------", 2 );
45274561
},
45284562

45294563
# called when a new connection comes in

0 commit comments

Comments
 (0)