Wb-rules молча "умирает" если сделать вложенное defineRule

Вчера наткнулся на неожиданное поведение сервиса wb-rules. Повисал так, что даже restart не помогал - он висел висел, убивал сервис по таймауту, снова запускал - и тот снова зависал. Выяснил путем экспериментов, что проблема во вложенном вызове defineRule. При этом я заливал по ssh старую версию проблемного js файла, перезагружал сервис, и все работало нормально:

defineRule(when: <condition>
  then: function(newValue){
    ...
    defuleRule(...); // вот после этой строчки все виснет намертво.
  };)

Нашел воркэраунд:

defineRule(
  when: ...
  then: function(newValue){
    ...
    setTimeout{function() { defuleRule(...); }, 0); // так не виснет
  };)

В документации про это ограничение ни слова. Ну и конечно хотелось бы максимум увидеть ексепшен, а не получить зависание целого сервиса… Воспроизвести проблему довольно легко, наверняка и правка будет простой. Если нужно, могу скинуть свой скрипт целиком.

Добрый день.
То есть при выполнении одного правила всякий раз создавался еще один новый экземпляр.
И таким образом создается несколько (десятков) тысяч объектов.

Максимальное количество объектов - не может быть заранее определено, поскольку зависит от того что в них выполняется (потребляемых ресурсов).
Но вообще создавать их динамически - можно, конечно, но никто на практике такого не делает. Так как количество контролов конечно - то правил больше чем объектов-источников событий и не нужно.

А на что исключение? По какому признаку?

То есть при выполнении одного правила всякий раз создавался еще один новый экземпляр.

Нет, при первом же вложенном вызове зависал сервис. Тысяч экземпляров не создавалось. Ну и алгоритмически было ограничение, разумеется, максимум создается около 10 правил (это часть алгоритма, ожидающего нужного момента при инициализации контроллера, чтобы обойти проблемы начальной настройки устройств).

И еще в поддержку своих слов добавлю, что setTimeout исключил проблему - алгоритм работает, “вложенные” правила добавляются в необходимом количестве, wb-rules справляется штатно.

А на что исключение? По какому признаку?

У меня нет опыта программирования в GO (я использую в работе в основном С/С++/С#), предположу, что тут случается дедлок:

func (engine *RuleEngine) RunRules(ctrlEvent *ControlChangeEvent, timerName string) {
	if wbgong.DebuggingEnabled() {
		wbgong.Debug.Println("[ruleengine] RunRules, event ", ctrlEvent, ", timer ", timerName)
		wbgong.Debug.Printf("[ruleengine] RulesLists for all: %v", engine.controlToRulesListMap)
	}
	engine.rulesMutex.Lock()    <------------
func (engine *RuleEngine) DefineRule(rule *Rule, ctx *ESContext) (id RuleId, err error) {
	engine.rulesMutex.Lock()    <------------

Сразу “отмажусь”! :slight_smile: Это лишь предположение, основанное на поверхностном анализе исходников на гитхабе! Но очевидно, думаю вы согласитесь, что зависание сервиса - это плохое поведение.

О, а давайте воспроизводящий пример, так точно не должно быть.

Как приятно общаться с профи! Не надо объяснять опасность рекурисии.

Естественно. Поэтому как только воспроизведу - сразу же сделаю багрепорт и разработчикам отдам.
Для полноты картины wb-rules версии 2.20.17?

Попробую вечером сделать небольшой скрипт, воспроизводящий проблему, отпишусь позже.

Вот 2 варианта скрипта. Первый “вешает” wb-rules на первой же итерации, второй отрабатывает нормально

var count = 4;

defineRule({
  when: function() {
    return count > 0;
  },
  then: function() {
    --count;
    log("1: count = " + count);
    defineRule({
      whenChanged: "wb-mdm3_101/K1",
      then: function () {
        log("2: count = " + count);
      },
    });
    log("3: count = " + count);
  },
});

var count = 4;

defineRule({
  when: function() {
    return count > 0;
  },
  then: function() {
    --count;
    log("1: count = " + count);
    setTimeout(function() {defineRule({
      whenChanged: "wb-mdm3_101/K1",
      then: function () {
        log("2: count = " + count);
      },
    })}, 0);
    log("3: count = " + count);
  },
});

Для полноты картины wb-rules версии 2.20.17?

так и не нашел, где посмотреть версию именно wb-rules… контроллер недавно обновил до 2407, предположу, что там должна быть последняя стабильная версия wb-rules.

Выполните в консоли

apt policy wb-rules
apt policy wb-rules
wb-rules:
  Установлен: 2.20.15
  Кандидат:   2.20.17
  Таблица версий:
     2.20.17 990
        990 http://deb.wirenboard.com/wb7/bullseye stable/main armhf Packages
 *** 2.20.15 100
        100 /var/lib/dpkg/status

Да, воспроизвел, на 2.20.17 - тоже.
Использую такой скрипт:

//09_23_test_01.js
var count = 0;

defineRule({
  when: function() {
    log("0: count = " + count);
    return count > 0;
  },
  then: function() {
    --count;
    log("1: count = " + count);
    defineRule({
      whenChanged: "wb-mdm3_101/K1",
      then: function () {
        log("2: count = " + count);
      },
    });
    log("3: count = " + count);
  },
});

При значении переменной “0” вижу ожидаемое выполнении функции:

ep 23 09:13:23 wirenboard-AYK5U4TB wb-rules[1970484]: INFO: [rule info] 0: count = 0
Sep 23 09:13:23 wirenboard-AYK5U4TB wb-rules[1970484]: INFO: [rule info] 0: count = 0
Sep 23 09:13:23 wirenboard-AYK5U4TB wb-rules[1970484]: INFO: [rule info] 0: count = 0
Sep 23 09:13:23 wirenboard-AYK5U4TB wb-rules[1970484]: INFO: [rule info] 0: count = 0
Sep 23 09:13:23 wirenboard-AYK5U4TB wb-rules[1970484]: INFO: [rule info] 0: count = 0
Sep 23 09:13:23 wirenboard-AYK5U4TB wb-rules[1970484]: INFO: [rule info] 0: count = 0
Sep 23 09:13:23 wirenboard-AYK5U4TB wb-rules[1970484]: INFO: [rule info] 0: count = 0
Sep 23 09:13:23 wirenboard-AYK5U4TB wb-rules[1970484]: INFO: [rule info] 0: count = 0
Sep 23 09:13:23 wirenboard-AYK5U4TB wb-rules[1970484]: INFO: [rule info] 0: count = 0
Sep 23 09:13:23 wirenboard-AYK5U4TB wb-rules[1970484]: INFO: [rule info] 0: count = 0

Пробую поменять значение на 2. Сохраняю, получаю вв логе:

Sep 23 09:14:08 wirenboard-AYK5U4TB wb-rules[1970484]: INFO: [rule info] 0: count = 0
Sep 23 09:14:08 wirenboard-AYK5U4TB wb-rules[1970484]: INFO: [rule info] 0: count = 0
Sep 23 09:14:08 wirenboard-AYK5U4TB wb-rules[1970484]: INFO: [rule info] 0: count = 0
Sep 23 09:14:08 wirenboard-AYK5U4TB wb-rules[1970484]: INFO: [rule info] 0: count = 2
Sep 23 09:14:08 wirenboard-AYK5U4TB wb-rules[1970484]: INFO: [rule info] 1: count = 1
Sep 23 09:14:09 wirenboard-AYK5U4TB wb-rules[1970484]: INFO: reloading file: /etc/wb-rules/09_23_test_01.js

Оформляю багу в трекер.

1 лайк