Killing executing scripts

Hi,

Still fairly new at this product. I’ve been building up Blockly scripts with generally a large degree of success. Generally I’m creating my logic in scripts and then calling it from a separate rule to act as a trigger.

I’ve noticed though, that scripts with timers can become runaway.

For instance, I’ve got a script running at the moment that has a timer block, checks for motion and will either turn off lights or reschedule itself to check again. Now, I had a bug in the motion check which meant that it’s never turning off, easy enough to fix. But now I’ve fixed it, the script is still logging output from the old version.

I’ve tried cancelling the timer from another script, but it doesn’t seem to do anything. So a couple of questions:

  1. Is it possible to interact with timers from another script?
  2. Is it possible to list and kill running scripts?

I’m slightly concerned that I could have any number of scripts quietly looping around consuming resources and not being tidied up that aren’t logging so I have no idea about. The only way I’ve found so far is to restart the OpenHAB process completely, which is slightly overkill imo.

Thanks.

  • Platform information:
    • Hardware: x64
    • OS: Linux/5.14.21-150400.24.49-default (amd64)
    • Java Runtime Environment: 11.0.18 (undefined)
    • openHAB version: openHAB 3.4.0.RC1

Sounds needlessly complicated and it eliminates the possibility for the code executed in the rule to know what Item and new states caused the rule to trigger. It’s much more standard to add Script Actions to your rules so the code and the triggers live together instead of being spread out all over the place.

If you are not using the shared cache (which I don’t think is available in Blockly until OH 4), your other script doesn’t have access to that timer. All variables in a script are local to that script and cannot be accessed from other scripts, even other scripts that are part of the same rule.

Only under very specific circumstances in OH 4. In OH 3.4 a concept of a sharedCache and privateCache was introduced. The sharedCache can be used by multiple scripts to access the same variable. But I don’t think support for that was added to Blockly until OH 4.

Even then, the sharedCache should be used only rarely. You should handle the full life cycle of a timer in the single script where possible.

No, but restarting OH will kill everything.

Unlikely.

Half-answering my own question, indeed it is documented that you cannot interact with a timer from another script. Although I’m unclear as to what defines an instance of a script (e.g. when a script is re-saved does that create a new instance).

So a new question - is there a static/global scope that things like timers can be registered against?

And the other question I’m still unsure about: is it possible to list and kill script processes that have runaway. I’ve found shell:threads, but I can’t seem to find my runaway script.

Yes, but the old instance is also destroyed. However, timers can become orphaned in the process, especially in older OH versions like 3.4 RC1 (why not at least the full release?).

See above.

No, see above. A timer is only executing when it’s actively running the code. If it’s merely scheduled it’s not running and therefore wouldn’t show up anywhere. And the thread that a timer uses is the same thread as the rule.

1 Like

For openHAB 4, Blockly will store timers in the private cache, which will solve the problem with orphaned timers because when a script is unload and removed, all timers in it‘s private cache are cancelled.

I think we already talked about having timers in shared cache, this is currently not possible from Blockly, but it could be implemented. WDYT?

There are a number of use cases where being able to access the same timer from multiple scripts would be useful. A simple one is a condition that only runs the script actions if a timer doesn’t exist.

I’m new to OpenHAB, nor am I a JS developer. But I found it surprising that there isn’t a globally accessible service registry for timers that can be retrieved and interacted with from any other script (irregardless of the method to implement them).

In the current form, one needs to encapsulate a lot of logic in a single script and take into account a lot of different circumstances which results in cumbersome conditional statements. By decoupling things like timers, you can have many bite-sized decision makers independently interact with polling/cycling timers. e.g. (door closed, find the timers dealing with lights and cancel them off).

Although off the top of my head I’d be concerned about how variables in the scope of the script and not the timer would then be passed to the timer etc. I haven’t really tried the approach of putting timers into their own script and using the context to call into that script to interact with the timer - I’m ignorant as to whether the called script is addresses the same static instance, or whether it would be pulled into the scope of the caller and thus continue the same problem of walls around timers.

There is, the shared cache. It’s just that Blockly at this moment doesn’t support it directly yet. See JavaScript Scripting - Automation | openHAB

In JavaScript the variables that exist at the time the timer is created are passed by reference. This means if the rule runs again later and changes the values of any variables, those changes will be reflected when the timer finally executes. If you want to fix the values of variables, in JavaScript you can use a function generator. See JavaScript Scripting - Automation | openHAB (for some reason I can’t get a link to the section, the function generator section immediately follows the accessing variables section).

When a rule calls another rule, the called rule runs in it’s own context. It does not inherit from the caller rule. However, you can pass data to the called rule.

Hi Rich,

do you mind opening an issue for that and maybe provide an idea how you would think a good block design could be and what the code would be that it should create?

cc: @florian-h05

Which part? Making it so timers can be saved in the shared cache? I would imagine it would not use a new block but instead an option would be provided on the existing after block that creates a timer. However, the reschedule, is running, etc. blocks become more challenging. How do they know where the Timer is stored?

Which part?
How to store timers in Blockly, that is. And then use it elsewhere.

This is why I ask you :smiley: because you are much more experienced on timers than I am :wink:

As Rich said, having a drop-down for private and shared cache.

The code would be nearly the same, just cache.shared instead of cache.private

1 Like

As I look at it, the other blocks become a little more complicated though as you’ll have to modify them too to tell the block where to look for the timer to reschedule it, for example.

Issue: [Blockly] Option to save a Timer in the shared cache · Issue #1858 · openhab/openhab-webui · GitHub

2 Likes

Yes, but this option is also needed if one rule should modify timers from another rule.