Register to post in forums, or Log in to your existing account
 

Play RetroMUD
Post new topic  Reply to topic     Home » Forums » CMUD Beta Forum
Kanonball
Novice


Joined: 06 Feb 2006
Posts: 48

PostPosted: Tue Nov 21, 2006 12:01 am   

infinite loops?
 
Is there some way to interrupt a script stuck in an infinite loop besides hitting the X button and closing cmud?
Reply with quote
MattLofton
GURU


Joined: 23 Dec 2000
Posts: 4834
Location: USA

PostPosted: Tue Nov 21, 2006 12:58 am   
 
You can try spamming mouseclicks over the little gun icon, that's the icon that turns off all triggers. Another great tip is to set a macro to fire off the #IGNORE command, which does the same thing.

Sounds like you have two triggers firing off of each other's output so this next bit probably isn't going to help, but in the case of a single trigger/alias/etc falling into an infinite loop ZMud will attempt to kill it automatically and forcing a prompt to you. If you click YES, then the infinite loop stops.
_________________
EDIT: I didn't like my old signature
Reply with quote
Kanonball
Novice


Joined: 06 Feb 2006
Posts: 48

PostPosted: Tue Nov 21, 2006 6:18 am   
 
Nop.. unfortunately it was a single trigger with a #while loop and a typo. I didnt see any dialogue. Maybe it isn't in cmud yet I guess.
Reply with quote
Vijilante
SubAdmin


Joined: 18 Nov 2001
Posts: 5182

PostPosted: Tue Nov 21, 2006 9:05 am   
 
The methods in zMud to stop run away scripts were #ABORT 1 at the command line or in a macro, pressing ESC at the command line. I haven't yet tested to make sure they still work in CMud, but I doubt they would have changed.

Also just as a generally good practice all #WHILE type loops should have 2 end conditions. One is used as a failure condition when inputs before the loop are bad.
_________________
The only good questions are the ones we have never answered before.
Search the Forums
Reply with quote
Zugg
MASTER


Joined: 25 Sep 2000
Posts: 23379
Location: Colorado, USA

PostPosted: Tue Nov 21, 2006 6:32 pm   
 
Well, this is actually a problem in CMUD that I haven't figured out how to handle.

In zMUD, loops would call the Windows "ProcessMessages" API to allow other messages to execute, such as keyboard and mouse events. However, data from the network is also handled as a message in Windows, so calling this within loops is what caused zMUD to process other MUD text while you were in a loop.

In CMUD we decided to let loops run completely *without* processing text from the MUD. And to increase the speed of loops, the ProcessMessages call was removed. This means that keyboard and mouse events are not recognized within a loop anymore.

So, pressing the ESC key to abort a loop no longer works. And I haven't figured out exactly how I want to handle this.

Using #ignore, #abort, etc also won't work, since CMUD isn't going to parse any other commands while it's in a loop. Again, this relates to the high-priority exclusive nature of loops in CMUD vs zMUD.
Reply with quote
The Raven
Magician


Joined: 13 Oct 2000
Posts: 463

PostPosted: Tue Nov 21, 2006 6:42 pm   
 
I definitely prefer CMUD's way of handling it. But we need some kind of way to break out. Is there a way to listen for just a specific keystroke and ignore all others (like Ctrl+Break)?
Reply with quote
MattLofton
GURU


Joined: 23 Dec 2000
Posts: 4834
Location: USA

PostPosted: Tue Nov 21, 2006 9:34 pm   
 
Quote:

In CMUD we decided to let loops run completely *without* processing text from the MUD. And to increase the speed of loops, the ProcessMessages call was removed. This means that keyboard and mouse events are not recognized within a loop anymore.


Erm, yeah, I was operating on all cylinders...in the wrong car. Embarassed

Any chance of a nanny thread or something similar (ie, something that can flip a switch somewhere to force the loop to be stopped)? Ideally, you'd want to control exactly what is processed, but I'd think an escape feature would be one of those always-available things even though macros and scripts wouldn't be (haven't a clue if there's any functionality out there for this as opposed to the all-or-nothing API, though, and I figure you aren't too keen on writing more 3rd-party stuff).
_________________
EDIT: I didn't like my old signature
Reply with quote
Vijilante
SubAdmin


Joined: 18 Nov 2001
Posts: 5182

PostPosted: Tue Nov 21, 2006 10:39 pm   
 
Zugg, I would suggest putting the ProcessMessages call back in, but having one of those global variables that you hate. The variable would just let other portions of the code know that the script is in a loop and certain messages should be held back with a PostMessage. That ProcessMessage call will likely be needed for some long loops to provide display updates to the status line. I had a few odd scripts that would scour a 10k room map and the status line would display progress and I think even a time estimate. I don't think any of that display update will occur without the call to ProccessMessages. Depending on how Delphi handles it you might have to cache the calls instead of reposting them.
_________________
The only good questions are the ones we have never answered before.
Search the Forums
Reply with quote
Zugg
MASTER


Joined: 25 Sep 2000
Posts: 23379
Location: Colorado, USA

PostPosted: Tue Nov 21, 2006 11:42 pm   
 
I'd rather not do this. ProcessMessages is the API call that is responsible for all of the mess with #WAIT. It ends up causing multiple message threads in an application, and if the application isn't perfectly designed for this (thread safe essentially) then you can get problems. It's not a simple matter of just blocking the network messages. You end up with alarms running in the middle of loops, etc. It becomes a real mess and it's something that I really want to clean up from zMUD.

In old versions of Windows, ProcessMessages was required to prevent an application from "hanging". Windows XP has a better multitasking model so that this doesn't happen. It doesn't prevent global system messages (so the system doesn't hang), but it just prevents messages within the current application.

What I will probably do is add a new CMUD command that will call ProcessMessages itself. Perhaps I'll add an #UPDATE command that will do this. Then you can put this into your loops yourself if you need stuff like the status window updates in long loops.

Since most loops are not 10k mapper loops that take forever, I'd rather have the default for normal users set to *not* call ProcessMessages, and let advanced users add this themselves as needed.

But either way, I still need a way to detect and handle infinite loops. But calling ProcessMessages is a last resort. Every time I have used this in the past it has caused endless trouble.
Reply with quote
The Raven
Magician


Joined: 13 Oct 2000
Posts: 463

PostPosted: Wed Nov 22, 2006 12:29 am   
 
There's always timer-based solutions (if ProcessMessages hasn't been called for a full 20 seconds, ask the user if they want to continue processing the script). I believe that's how web browsers do it when long javascripts hang.
Reply with quote
Vijilante
SubAdmin


Joined: 18 Nov 2001
Posts: 5182

PostPosted: Wed Nov 22, 2006 11:32 am   
 
This is the code I use in a few of my processor heavy loops
Code:
   if(PeekMessage(&mess,NULL,0,0,PM_NOREMOVE)) {
    if(PeekMessage(&mess,NULL,WM_DESTROY,WM_DESTROY,PM_NOREMOVE)) {
     return(-100);
    } else {
     GetMessage(&mess,NULL,0,0);
     TranslateMessage(&mess);
     DispatchMessage(&mess);
    }
   }

It checks to see if there are any messages, then checks for a destroy message. On a destroy it just exits the entire routine with an error, otherwise it allows processing of a message. You might be able to do something similar in the handling of scripts with a small button near the command line for abort or just the ESC key. Then the only message you would be looking for is the specific abort method. No matter what one is needed. Everyone accidentally makes a bad loop from time to time.
_________________
The only good questions are the ones we have never answered before.
Search the Forums
Reply with quote
Zugg
MASTER


Joined: 25 Sep 2000
Posts: 23379
Location: Colorado, USA

PostPosted: Fri Nov 24, 2006 11:17 pm   
 
OK, I think I've got this fixed pretty nicely now.

As suggested by Vijilante, I'm doing my own message processing when the script engine is in a loop (#WHILE, #LOOP, etc). It allows all messages except for the network messages to be processed. So not only can you press ESC to abort an infinite loop, you can even do something like this:
Code:
a=1
#while (@a=1) {#add b 1;#show @b}
...now it starts spamming the screen with the @b values
...but the command line is still active, so we can do this
a=2
...and now the loop stops
Reply with quote
Arminas
Wizard


Joined: 11 Jul 2002
Posts: 1265
Location: USA

PostPosted: Fri Nov 24, 2006 11:21 pm   
 
Sweet. Nice job Zugg!
_________________
Arminas, The Invisible horseman
Windows 7 Pro 32 bit
AMD 64 X2 2.51 Dual Core, 2 GB of Ram
Reply with quote
Seb
Wizard


Joined: 14 Aug 2004
Posts: 1269

PostPosted: Sat Nov 25, 2006 1:27 am   
 
That sounds good Zugg. But what happens if you have an alias A that calls alias B that calls alias C that calls alias A? Does ESC work for that kind of infinite loop too now?
Reply with quote
Zugg
MASTER


Joined: 25 Sep 2000
Posts: 23379
Location: Colorado, USA

PostPosted: Sat Nov 25, 2006 3:27 am   
 
What we are talking about here is infinite loops in stuff like While, Loop, Until, etc. These are tight loops that were not allowing event processing. Alias loops like you mentioned are already handled by the existing alias loop code and isn't really related to what I was talking about in this topic.
Reply with quote
Display posts from previous:   
Post new topic   Reply to topic     Home » Forums » CMUD Beta Forum All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum

© 2009 Zugg Software. Hosted by Wolfpaw.net