Register forum user name Search FAQ

Gammon Forum

Notice: Any messages purporting to come from this site telling you that your password has expired, or that you need to verify your details, confirm your email, resolve issues, making threats, or asking for money, are spam. We do not email users with any such messages. If you have lost your password you can obtain a new one by using the password reset link.

Due to spam on this forum, all posts now need moderator approval.

 Entire forum ➜ MUSHclient ➜ General ➜ strange problem about trigger linkage

strange problem about trigger linkage

It is now over 60 days since the last post. This thread is closed.     Refresh page


Posted by Zhenzh   China  (68 posts)  Bio
Date Tue 03 Sep 2019 05:25 AM (UTC)
Message
I have two functions as below:

function test1()
  AddTriggerEx("test1", "^trigger test1$", "Note('trigger1 executed') test2()",
               bit.bor(trigger_flag.Enabled,
                       trigger_flag.RegularExpression,
                       trigger_flag.Temporary,
                       trigger_flag.OneShot,
                       trigger_flag.KeepEvaluating),
               -1, 0, "", "", sendto.script, 100)
end

function test2()
  AddTriggerEx("", "^trigger test2$", "Note('trigger2 executed')",
               bit.bor(trigger_flag.Enabled,
                       trigger_flag.RegularExpression,
                       trigger_flag.Temporary,
                       trigger_flag.OneShot),
               -1, 0, "", "", sendto.script, 99)
end


What I expected is:
1. run test1(), trigger "test1" is created
2. trigger line "^trigger test1$" is coming, trigger "test1" do inline script
3. test2() is run by trigger "test1", trigger "test2" is created
4. trigger "test1" is deleted by one shot flag
5. trigger line "^trigger test2$" is coming, trigger "test2" do inline script
6. trigger "test2" is deleted by one shot flag

While the actual result is the inline script of trigger "test1" being invoked constantly (seems get dead loop), and the mushclient get hung at the end.


[2019-09-03 13:32:18] 
[2019-09-03 13:32:18] 
[2019-09-03 13:32:18] 
[2019-09-03 13:32:19] 
[2019-09-03 13:32:19] 
[2019-09-03 13:32:19] 
[2019-09-03 13:32:19] 
[2019-09-03 13:32:19] 
[2019-09-03 13:32:43] trigger1 executed
[2019-09-03 13:32:43] trigger1 executed
[2019-09-03 13:32:43] trigger1 executed
[2019-09-03 13:32:43] trigger1 executed
[2019-09-03 13:32:43] trigger1 executed
[2019-09-03 13:32:43] trigger1 executed
[2019-09-03 13:32:43] trigger1 executed
[2019-09-03 13:32:43] trigger1 executed
[2019-09-03 13:32:43] trigger1 executed
[2019-09-03 13:32:43] trigger1 executed
[2019-09-03 13:32:43] trigger1 executed
[2019-09-03 13:32:43] trigger1 executed
[2019-09-03 13:32:43] trigger1 executed
[2019-09-03 13:32:43] trigger1 executed
[2019-09-03 13:32:43] trigger1 executed
[2019-09-03 13:32:43] trigger1 executed
[2019-09-03 13:32:43] trigger1 executed
...
Top

Posted by Zhenzh   China  (68 posts)  Bio
Date Reply #1 on Tue 03 Sep 2019 05:39 AM (UTC)
Message
I have had some investigation and find such issue only occurs when a smaller sequence AddTriggerEx() is invoked in inline script of another bigger sequence AddTriggerEx().

Any trigger should only be active once for the same matching line, isn't it?

I'm puzzled what cause the trigger "test1" get active all the time over the same trigger line?
Top

Posted by Nick Gammon   Australia  (23,173 posts)  Bio   Forum Administrator
Date Reply #2 on Tue 03 Sep 2019 07:09 AM (UTC)

Amended on Tue 03 Sep 2019 07:10 AM (UTC) by Nick Gammon

Message

Thank you for the very good description. :)

It seems to me that what is happening is that, by adding a lower-sequence trigger you are “pushing” up all the triggers in the list of the triggers to be evaluated.

So, for example, you start with:

test1 trigger  <-- 1: current trigger
something else <-- 2: next trigger to be evaluated

Now the line arrives with test1 in it and that adds a new trigger:

test2 trigger  <-- 1: current trigger
test1 trigger  <-- 2: next trigger to be evaluated
something else <-- 3: some other trigger

The client now moves onto trigger 2 in the list (which is now test1) and evaluates it again. This adds a new test2 trigger, so that now the test1 trigger is in position 3, and is evaluated again. And so on.

You will note from my page How MUSHclient processes text arriving from the MUD that deleting one-shot triggers is one of the last things to be done when processing an input line.

I’m not sure of a good rule to avoid this, which won’t affect existing trigger processing. Possibly a flag in the trigger processing which makes it skip any trigger which has already been processed might do it.


- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

Posted by Nick Gammon   Australia  (23,173 posts)  Bio   Forum Administrator
Date Reply #3 on Tue 03 Sep 2019 07:11 AM (UTC)
Message
As a work-around, can you instead enable and disable triggers, rather than adding and deleting them? That would avoid the issue of changing the length of the triggers list.

- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

Posted by Zhenzh   China  (68 posts)  Bio
Date Reply #4 on Tue 03 Sep 2019 08:29 AM (UTC)
Message
I'm now turn off the KeepEvaluating for the trigger test1 as a work around.

It can avoid the issue, but I have to carefully think over the use of the KeepEvaluating switch for all exiting triggers to avoid new issues being involved by turning of KeepEvaluating.
Top

Posted by Nick Gammon   Australia  (23,173 posts)  Bio   Forum Administrator
Date Reply #5 on Wed 04 Sep 2019 05:55 AM (UTC)
Message
I think playing with the trigger list, whilst triggers are being evaluated, is an inherently dangerous thing to do. It's like iterating through an array, and adding a new item to the start if some condition is met.

Assuming you don't have to do this hundreds of times, it would be safer to have a disabled trigger with the correct sequence sitting there waiting to be enabled. You could always change what the match text is before enabling it.

- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

Posted by Zhenzh   China  (68 posts)  Bio
Date Reply #6 on Wed 18 Sep 2019 02:14 PM (UTC)
Message
I have an idea for resolving such issue.

For all adding/removing trigger requests from "send to" and "script file", compare the sequence.

If the sequence of trigger to be added/removed is larger than the processing trigger, do add/remove immediately as current design.(updating order of trigger after processing trigger will not impact on the result of processed triggers)

If the sequence of trigger to be added/removed is lessequal than the processing trigger, record the add/remove action in a temporary array instead of doing immediately. Add one more step for processing these recorded adding/removing at the end of the process arriving text.(Your page "How MUSHclient processes text arriving from the MUD" mentioned step 21 is deleting one-shot triggers. Additional step 22 is need to processing adding/removing triggers in temporary array)
Top

Posted by Nick Gammon   Australia  (23,173 posts)  Bio   Forum Administrator
Date Reply #7 on Thu 19 Sep 2019 08:59 PM (UTC)
Message
This could get rather painful. What if you add a trigger with a lower sequence number (and it goes into this special array) and then you do something like enable the trigger? Since it won't be found in the normal trigger list the enable will fail. Unless trigger commands (like delete trigger, enable, get information, etc.) all take this second array of triggers into account, then these operations won't work.

- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

Posted by Zhenzh   China  (68 posts)  Bio
Date Reply #8 on Fri 20 Sep 2019 04:30 AM (UTC)
Message
How about using two trigger list, one for process order only?

At the beginning of processing arriving text, create a copy of the trigger list to be used for processing order.

Any higher sequence trigger operation may impact on the order list such as add/remove/enable/disable will update both original and copy list and the other operation updates the original list only.

So that getting info operation can always get the exact trigger info from original list while the arriving text process flow read copy list to handle the correct trigger list.
Top

Posted by Nick Gammon   Australia  (23,173 posts)  Bio   Forum Administrator
Date Reply #9 on Fri 20 Sep 2019 05:42 AM (UTC)
Message

OK, but what if a low-sequence trigger is designed to add a high-sequence trigger, so that the same line can match the second (newly added) trigger? If we make a copy of the list then the new trigger won’t be in the copy.

Probably the least-impact change would be, at the start of trigger processing, to mark all triggers as not evaluated, and then when evaluating them mark them as evaluated. When working down the list, disregard any triggers that have already been evaluated.

Even then I can imagine problems. Say a trigger inserts a whole lot of lower-sequence triggers, then where does evaluation of the next trigger start?

And your idea of making a copy doesn’t totally work, because if we copy pointers then we could get a crash if the trigger has been deleted (and thus the pointer invalidated) and if we do a deep copy (copy the whole trigger) then any changes made by earlier triggers won’t affect the copy.

I don’t think there is an easy solution, except to not add triggers during trigger evaluation, particularly lower-sequence ones.

This is starting to sound like an X-Y Problem - why do you want to do this?


- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

Posted by Zhenzh   China  (68 posts)  Bio
Date Reply #10 on Fri 20 Sep 2019 07:58 AM (UTC)
Message
The evaluation mark solution also has a problem.
Imagine such scenario:

function fail_retry()
  AddTriggerEx("", "failed message", "fail_retry()", ...)
  <delay some time>
  <do something>
end


A failure retry function, player do some action, different function will be invoked based on the result.
When the action failed, the new added trigger will be matched by the failed message so that fail_retry() will be invoked again until action success.

Here comes the problem:
As each time the retry function is invoked, a new trigger will be added.
Since both match line and sequence created by retry function are the same, the new trigger may be added follow the lasted created trigger.
If the keep_evaluation is enabled, process flow will continue matching triggers. The new added trigger happened to be on the next position and has no evaluated mark.

Thus cause a dead loop like: retry() -> add trigger -> do action -> process added trigger -> retry() -> add trigger -> process added trigger -> retry() -> ...
Top

Posted by Zhenzh   China  (68 posts)  Bio
Date Reply #11 on Fri 20 Sep 2019 08:06 AM (UTC)

Amended on Fri 20 Sep 2019 09:04 AM (UTC) by Zhenzh

Message
Nick Gammon said:

if we do a deep copy (copy the whole trigger) then any changes made by earlier triggers won’t affect the copy.


Is it possible to manually update both list? For example, when new higher sequence trigger is inserted to the original list, do additional array insert to the copy list at the same position as I mentioned.

Zhenzh said:

Any higher sequence trigger operation may impact on the order list such as add/remove/enable/disable will update both original and copy list
Top

Posted by Nick Gammon   Australia  (23,173 posts)  Bio   Forum Administrator
Date Reply #12 on Fri 20 Sep 2019 10:11 PM (UTC)
Message
What is wrong with my suggestion of enabling and disabling the trigger, rather than adding and deleting it?

- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

Posted by Zhenzh   China  (68 posts)  Bio
Date Reply #13 on Sat 21 Sep 2019 08:16 AM (UTC)
Message
enabling/disabling soluation has no problem. I'm now using it.
The only disadvantage is reading code get a little harder as operation against trigger name can not fully indicate the use of a trigger compare to what an addtrigger funtion do.
Top

The dates and times for posts above are shown in Universal Co-ordinated Time (UTC).

To show them in your local time you can join the forum, and then set the 'time correction' field in your profile to the number of hours difference between your location and UTC time.


41,858 views.

It is now over 60 days since the last post. This thread is closed.     Refresh page

Go to topic:           Search the forum


[Go to top] top

Information and images on this site are licensed under the Creative Commons Attribution 3.0 Australia License unless stated otherwise.