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

Play RetroMUD
Post new topic  Reply to topic     Home » Forums » CMUD General Discussion
geniusclown
Magician


Joined: 23 Apr 2003
Posts: 358
Location: USA

PostPosted: Sat Aug 20, 2011 1:27 pm   

CMUD locking up
 
I've been having a problem with CMUD completely locking up, after being online for anywhere from a few seconds to a few hours. The computer is fine - I can still work with other programs and force CMUD down with the Task Manager, but CMUD itself becomes completely nonreactive, unable to scroll windows or execute menu options. Sometimes instead of locking up, I get very strange messages such as "ERROR: Operation divide by zero requires two arguments" (as far as I know, you can never divide by zero, regardless of how many arguments you use). When I get these messages, the scripts continue running for several minutes before the program locks up. I rarely get the error dump from CMUD itself.

While composing this post, I got for the first time an error from CMUD, several times, saying "Thread creation error: Not enough storage is available to process this command." and I discovered that CMUD is using 1.7 GB of computer memory.

I have already backed up to XML, uninstalled and reinstalled CMUD. I have disabled classes when they're not being used, and the only classes that have been active every time I've locked up are my core scripts that regulate all my other complex scripts.

This for for Dragonrealms, and all of this code is original so if explanation is needed, I can definitely provide. If anything looks awry and/or simplifiable, I would greatly appreciate it. Here is the code:

Code:

<class name="Core" id="1">
  <class name="roundtimer" id="2">
    <button type="Gauge" autosize="false" width="80" height="15" toolbar="2" toolstyle="true" color="red" textcolor="white" gaugelowcol="None" priority="7" id="3">
      <caption>RT: %if(@stunned,"STUNNED!",%leftback(%int(@/core/roundtimer/rt+900),3))</caption>
      <value>rt</value>
      <expr>@rt</expr>
      <gaugemax>@rtm</gaugemax>
    </button>
    <var name="rt" type="Integer" usedef="true" id="4">
      <value>2125</value>
      <default>0</default>
    </var>
    <var name="rtm" type="Integer" usedef="true" id="5">
      <value>3000</value>
      <default>1</default>
    </var>
    <trigger name="rtDetect" type="Expression" priority="4" newline="false" id="6">
      <pattern>@/core/roundtimer/rt>0 and !%trigger(rtCount)</pattern>
      <value>#T+ /core/roundtimer/rtCount
#ADD CorePulse 1</value>
    </trigger>
    <trigger priority="300" id="7">
      <pattern>Roundtime{:|}%s(%n) sec</pattern>
      <value>/core/roundtimer/rtEnd=@timecode+%1*1000-@/core/roundtimer/lag
/core/roundtimer/rt=%1*1000
/core/roundtimer/rtm=%1*1000</value>
    </trigger>
    <var name="lag" type="Integer" id="8">250</var>
    <var name="rtEnd" usedef="true" id="9">
      <value>1756752234</value>
      <default>0</default>
    </var>
    <alias name="rt" id="10">
      <value>/core/roundtimer/rtEnd=@timecode+250
/core/roundtimer/rt=@/core/roundtimer/rt+250</value>
    </alias>
    <trigger priority="9630" id="11">
      <pattern>^...wait (%n) seconds.</pattern>
      <value>pq @/core/roundtimer/queueExec
/core/roundtimer/queueExec=""
/core/roundtimer/rtEnd=@timecode+%1*1000
/core/roundtimer/rt=%1*1000
#IF (%inwalk) {#STOP;#T+ ContinuePath}</value>
    </trigger>
    <var name="rtIncrement" type="Float" id="12">0.3</var>
    <trigger name="rtCount" type="Alarm" priority="5" trigontrig="false" newline="false" id="13">
      <pattern>@/core/roundtimer/rtIncrement</pattern>
      <value>/core/roundtimer/rt=@/core/roundtimer/rtEnd-@timecode
#IF (@/core/roundtimer/rt<0) {
  /core/roundtimer/rt=0
  #T- /core/roundtimer/rtCount
  }</value>
    </trigger>
    <var name="queueExec" type="Literal" id="15"/>
  </class>
  <class name="gsl" id="20">
    <var name="stunned" type="Integer" id="21">0</var>
    <var name="lefthand" id="22">Empty</var>
    <var name="righthand" id="23">Stiletto</var>
    <var name="stat" id="24">Hidden </var>
    <var name="position" type="Literal" id="25">Standing </var>
    <trigger type="GSL" priority="50" newline="false" id="26">
      <pattern>l</pattern>
      <value>#FORALL {%replace(%gsl(l)," ",|)} {#IF (%i) {lefthand=%proper(%i)}}</value>
    </trigger>
    <trigger type="GSL" priority="51" newline="false" id="27">
      <pattern>m</pattern>
      <value>#FORALL {%replace(%gsl(m)," ",|)} {#IF (%i) {righthand=%proper(%i)}}</value>
    </trigger>
    <trigger type="GSL" priority="52" newline="false" id="28">
      <pattern>P</pattern>
      <value>/Core/gsl/stat=""
#IF %match( %gsl( P), B) {/Core/gsl/stat=@stat"DEAD! "}
#IF %match( %gsl( P), I) {
  /Core/gsl/stat=@stat"Stunned! "
  /Core/gsl/stunned=1
  /Core/roundtimer/rt=2
  /Core/roundtimer/rtm=1
  #T- rtDetect
  } {
  /Core/gsl/stunned=0
  #T+ rtDetect
  }
#IF %match( %gsl( P), O) {/Core/gsl/stat=@stat"Bleeding! "}
#IF %match( %gsl( P), N) {
  /Core/gsl/stat=@stat"Hidden "
  /Core/gsl/Hidden=1
  } {/Core/gsl/Hidden=0}
#SWITCH (%match( %gsl( P), GH)) {/Core/gsl/position="Kneeling "}
 (%match( %gsl( P), G)) {/Core/gsl/position="Prone "}
 (%match( %gsl( P), H)) {/Core/gsl/position="Sitting "}
 (1) {/Core/gsl/position="Standing "}
/Core/gsl/stat=@stat%if( @position<>"Standing ", @position)
#IF %match( %gsl( P), P) {/Core/gsl/stat=@stat"in group "}
#IF %match( %gsl( P), J) {/Core/gsl/stat=@stat"Busy...? "}</value>
    </trigger>
    <button autosize="false" width="100" height="15" toolbar="2" priority="53" id="30">
      <caption>L: @lefthand</caption>
    </button>
    <button autosize="false" width="100" height="15" toolbar="2" priority="55" id="31">
      <caption>R: @righthand</caption>
    </button>
    <stat name="Statline" priority="60" id="32">
      <value>%if(@CorePulse,,)~[%gsl(p)~] %replace(%gsl(j),|,"   ")</value>
    </stat>
    <var name="CorePulse" type="Integer" id="33">165984</var>
    <var name="Hidden" id="34">1</var>
    <trigger type="GSL" priority="1334970" id="35">
      <pattern>q</pattern>
      <value>#ADD CorePulse 1</value>
    </trigger>
  </class>
  <class name="queue" id="36">
    <var name="loop" type="StringList" id="37">
      <value>jab|kick|feint|lunge|thrust</value>
      <json>["jab","kick","feint","lunge","thrust"]</json>
    </var>
    <alias name="q" id="38">
      <value>#IF (%1) {#IF (@/core/queue/queue) {/core/queue/queue=%concat(@/core/queue/queue,|,%-1)} {/core/queue/queue=%-1}} {/core/queue/queue="";rt}</value>
    </alias>
    <alias name="loop" id="39">
      <value>/core/queue/loop=%-1</value>
    </alias>
    <alias name="qc" id="40">
      <value>/core/queue/loop=""
/core/queue/queue=""
/core/queue/queueExec=""
#T+ /core/queue/queueTick
#T- /core/queue/queueTock
#ECHO ---queue and loop cleared---</value>
    </alias>
    <alias name="qn" id="41">
      <value>q  %concat(  %replace( {%-1}, |, " noRt|"), " noRt")</value>
    </alias>
    <trigger name="queueTock" type="Expression" priority="6" trigontrig="false" newline="false" enabled="false" id="42">
      <pattern>@/core/roundtimer/rt>0</pattern>
      <value>#T- queueTock
/core/queue/queueExec=""
#T+ queueTick</value>
    </trigger>
    <stat name="Status Window" showinbar="false" showinwindow="true" id="43">
      <value><![CDATA[%if(@CorePulse,,)<font terminal 8><u>%concat(%ansi(cyan,high),%repeat(" ",%eval(@STWColumnWidth-2)),%if(%numitems(@queue)<10," "),%numitems(@queue)," ",</u>,%if(%trigger(queueTick),I,O),<u>,%ansi(magenta,high)," ",%numitems(@loop),%if(%numitems(@queue)<10," "),%repeat(" ",%eval(@STWColumnWidth-4)),</u>)
%ansi(cyan,high) @column(@queue.6) %ansi(magenta,high)%delete(@loop.6,@STWColumnWidth,500)
%ansi(cyan,high) @column(@queue.5) %ansi(magenta,high)%delete(@loop.5,@STWColumnWidth,500)
%ansi(cyan,high) @column(@queue.4) %ansi(magenta,high)%delete(@loop.4,@STWColumnWidth,500)
%ansi(cyan,high) @column(@queue.3) %ansi(magenta,high)%delete(@loop.3,@STWColumnWidth,500)
%ansi(cyan,high) @column(@queue.2) %ansi(magenta,high)%delete(@loop.2,@STWColumnWidth,500)
<u>%ansi(cyan,high) @column(@queue.1)</u> <u>%ansi(magenta,high)%delete(@loop.1%repeat(" ",@STWColumnWidth),@STWColumnWidth,500)</u>
<font calibri 11> %ansi( green, high) @queueExec
<font calibri 12> %ansi(yellow,high) %repeat(" ",%eval(40-%len(@Stat))) @Stat
]]></value>
    </stat>
    <trigger name="queueTick" type="Expression" priority="5" trigontrig="false" newline="false" id="44">
      <pattern>@/core/roundtimer/rt=0 and (%numitems(@/core/queue/queue) or %numitems(@loop))</pattern>
      <value>#T- queueTick
#IF (@/core/queue/queue) {/core/queue/queueExec=%pop(queue)} {/core/queue/queueExec=%item(@/core/queue/loop,1);/core/queue/loop=%additem(%pop(/core/queue/loop),@/core/queue/loop)}
#EXEC %replace(@/core/queue/queueExec," noRt","")
#T+ queueTock
#IF (%ends(@/core/queue/queueExec," noRt")) {#ALARM +.05 {rt} Core/queue}</value>
    </trigger>
    <var name="queueExec" type="Literal" id="45"/>
    <var name="STWColumnWidth" type="Integer" id="46">21</var>
    <var name="queue" id="47">
      <value>back</value>
      <json>["back"]</json>
    </var>
    <alias name="pq" id="48">
      <value>#IF (@/core/queue/queue) {/core/queue/queue=%concat(%-1,"|",@/core/queue/queue)} {/core/queue/queue=%-1}</value>
    </alias>
    <func name="column" id="49">
      <value>#RETURN %switch(%len(%1)<=@STWColumnWidth,%concat(%repeat(" ",%eval(@STWColumnWidth-%len(%1))),%1),%ends(%1," noRt"),%concat(%delete(%1,%eval(@STWColumnWidth-5),500),"..noRt"),1,%concat(%delete(%1,%eval(@STWColumnWidth-1),500),".."))</value>
    </func>
    <alias name="dq" id="50">
      <value>#CALL %pop(/core/queue/queue)
#ADD CorePulse 1</value>
    </alias>
    <alias name="nl" id="51">
      <value>/core/queue/loop=%additem(%pop(/core/queue/loop),@/core/queue/loop)</value>
    </alias>
  </class>
</class>
<var name="timecode" id="11">
  <value>%eval(%time(d)*86400000+%time(h)*3600000+%time(n)*60000+%time(s)*1000+%time(z))</value>
</var>
<func name="lastword" id="173">
  <value>#RETURN  %word(%-1,%numwords(%-1))</value>
</func>
<func name="tolist" id="174">
  <value>#RETURN  %replace(%replace(%replace(%1,", and ","|")," and ","|"),", ","|")</value>
</func>
_________________
.geniusclown
Reply with quote
geniusclown
Magician


Joined: 23 Apr 2003
Posts: 358
Location: USA

PostPosted: Sat Aug 20, 2011 1:44 pm   
 
The memory thing must have been a fluke. I got the error twice, then left my Process Explorer open to watch the memory usage while doing things like opening the map, and it didn't happen again. It's been stable for 10 minutes of full-on scripting now using only 52 Mb of memory.
_________________
.geniusclown
Reply with quote
geniusclown
Magician


Joined: 23 Apr 2003
Posts: 358
Location: USA

PostPosted: Thu Aug 25, 2011 2:40 pm   
 
I'm continuing to have lockup issues with CMUD, and am no closer to finding the cause. I need suggestions to track down this annoying bug. What tools are there other than the script debugger (which has been useless in this issue) to help identify what's causing CMUD to lock up?
_________________
.geniusclown
Reply with quote
Fizgar
Magician


Joined: 07 Feb 2002
Posts: 333
Location: Central Virginia

PostPosted: Thu Aug 25, 2011 7:26 pm   
 
One thing you can try, is to read the following two posts and make the changes they refer to in your script above.

http://forums.zuggsoft.com/forums/viewtopic.php?t=36226
http://forums.zuggsoft.com/forums/viewtopic.php?p=113326

More specifically what I am talking about is the way you are referencing and assigning variables incorrectly.

edit:
I had a bit of a headache earlier making staring at the xml a bit difficult. After a hand full of aspirin and and a nap, I looked the code over again. Since it looks like core is a class and not the main window/module those posts won't help much. Sorry about that.
_________________
Windows Vista Home Premium SP2 32-bit
AMD Athlon Dual Core 4400+ 2.31 GHz
3 GB RAM
CMUD 3.34
Reply with quote
geniusclown
Magician


Joined: 23 Apr 2003
Posts: 358
Location: USA

PostPosted: Fri Aug 26, 2011 4:56 am   
 
I appreciate the input anyhow. I read those posts and learned something... my choice early on was to avoid different packages or windows. I only format secondary windows using %ansi so that things don't get confused like I read about in those other posts. I did change the variable assignments to be explicit from the module's root to avoid other confusions I noticed happening.

I'm completely baffled with my lockups. Yesterday it locked up 5 times in a row, within a few minutes of each other while doing entirely different things (twice outside of roundtime, so these core scripts were unlikely to have caused the lockup), but today I've logged about 6 hours without a single critical error.

One error I AM getting that I can't explain and may be related is this: every once in a while, the Status Window's display is shown in the primary game window and sent to the MUD. Anyone familiar with this error?
_________________
.geniusclown
Reply with quote
Rahab
Wizard


Joined: 22 Mar 2007
Posts: 2320

PostPosted: Fri Aug 26, 2011 1:21 pm   
 
It sounds like you have either a runaway loop or are accidentally creating a ton of threads, which are eating up all the CPU and freezing your Cmud. That's a very complicated script, and I can't tell at first glance whether there are any problems in it. The only thing that leaps out at me is that you use #EXEC when you don't have to. #EXEC is slow and should be avoided whenever possible. Code in #EXEC is not compiled, and has to be compiled during runtime. I think you can use #CALL in that particular instance. However, I don't think that is your problem. It looks like there may be some triggers that fire frequently. But this script is too complicated for a quick analysis.
Reply with quote
geniusclown
Magician


Joined: 23 Apr 2003
Posts: 358
Location: USA

PostPosted: Fri Aug 26, 2011 10:41 pm   
 
I realize it's complex, and that's why I'm asking the experts here. =P

The only use of #EXEC is intentional because some scripts pass a variable into the queue that needs to be evaluated at runtime. It's never more complicated than a variable substitution or an %if.

I have looked very carefully at all of my loops and waits, and I can't find any that could go infinite.

Any comment on the information that's supposed to be in the status window being sent to the MUD? What could possibly cause that to happen?
_________________
.geniusclown
Reply with quote
MattLofton
GURU


Joined: 23 Dec 2000
Posts: 4834
Location: USA

PostPosted: Sat Aug 27, 2011 3:33 am   
 
My guess is that you have too much of a process load hitting CMud all at once. I see the same thing with the reception of the raw GMCP strings that CMud parses into the various %gmcp values, but it only happens when I'm on a speedwalk and Aard's sending me hundreds of lines in a very short span.
_________________
EDIT: I didn't like my old signature
Reply with quote
geniusclown
Magician


Joined: 23 Apr 2003
Posts: 358
Location: USA

PostPosted: Sun Aug 28, 2011 2:21 pm   
 
I get locked up even when doing very mundane things that cause very little MUD output; it can go hours with no lockup when in combat and dozens of triggers are firing all at once. I'm going to study #THREAD and see if there's a solution in there... any strategies for using it would be appreciated.

Perhaps this is another clue: sometimes I get a bunch of errors referring to commands that I don't use. For example
Quote:
ERROR: Operator unrecognized function requires two arguments
ERROR: Operator trigger pattern expected requires two arguments
ERROR: Operator CONCAT requires two arguments
ERROR: Operator CONCAT requires two arguments
ERROR: Operator CONCAT requires two arguments
ERROR: Operator CONCAT requires two arguments
ERROR: Operator CONCAT requires two arguments
ERROR: Operator CONCAT requires two arguments
ERROR: Operator CONCAT requires two arguments
ERROR: Operator CONCAT requires two arguments
ERROR: Operator CONCAT requires two arguments
ERROR: Operator CONCAT requires two arguments
ERROR: Operator EQ requires two arguments


I'm not sure what operator EQ is. Certainly, operator "trigger function expected" isn't an operator but a message that the parser might tell the user. I've also gotten "Operator divide by zero requires two arguments" which just doesn't make sense - it's not an operation and besides, you can't divide by zero regardless of how many arguments you have!

Also, when I get these errors, the program continues running. Is it possible that these errors are causing the lockups, but is non-terminal on occasion? How can I find what's causing these errors? Are there any monitors or other built-in tools or plug-ins to help me track this? Script Debugger is useless in this case.
_________________
.geniusclown
Reply with quote
geniusclown
Magician


Joined: 23 Apr 2003
Posts: 358
Location: USA

PostPosted: Mon Aug 29, 2011 3:29 am   
 
Here's another oddity that keeps cropping up... some of the scripts stop working. It seems to be the trigger rtDetect (code above) that's not activating. If I manually "Execute script" from the Package Editor, it will fire. Once. But the button gauges stop updating automatically. If I disable the "Core" class, they all vanish, as expected, but when I re-enable the class, they don't reappear. Buttons in other classes will disappear and reappear when their respective classes are turned on or off, and all other triggers fire, but my Core class just stops working. The only way I can get it to fix is to restart CMUD. Note that if I save the package while it's in this non-functional state then restart CMUD, it works normal.
_________________
.geniusclown
Reply with quote
geniusclown
Magician


Joined: 23 Apr 2003
Posts: 358
Location: USA

PostPosted: Thu Sep 01, 2011 2:42 pm   
 
This issue is not resolved, but I may be closer to the solution. I've adjusted the triggers in the core scripts to use "#SECTION". This has reduced the frequency of random lockups, but hasn't stopped them - it still occasionally locks up within 3 minutes 4 or 5 times in a row, then runs for an hour or more without any errors. Also, I now occasionally "see" what the lockup is - I get two error messages that alternate and give infinite scroll. Because it's scrolling too fast, I can't read the messages, but they both start with "ERROR: Operation", and I'm pretty sure one of them says "CONCAT requires two arguments", and the other says some other operation requires two arguments, which is longer than "CONCAT" and is not all caps, but beyond that I can't tell what it is.

Big question: When I get these "ERROR: Operation ______ requires two arguments" errors, is there any way to figure out what code is producing the error? Maybe a debug setting or logfile that I haven't discovered?

The script debugger doesn't work like I expect. I've read the documentation and figured out a few things, but there's still a lot of mystery behind it - is there documentation somewhere other than internally? Biggest issue I have is that when I deselect a single class from the class tree (as I attempt to narrow down the error), the debugger stops completely. So either it shows all debugging messages or none. Another big issue is if the program locks up and the debugger window isn't already in the front, I can't see what's on it! When I bring it to the front while CMUD is locked up, it doesn't refresh the debugger window at all.
_________________
.geniusclown
Reply with quote
SpiritWolf
Wanderer


Joined: 02 Jul 2002
Posts: 74
Location: USA

PostPosted: Thu Sep 01, 2011 5:24 pm   
 
Just a suggestion, but if you know concat is giving you issues, maybe set some debugging echoes that tell you whats going on before and after your concats? Looks like you've only got seven of them, so it shouldn't take much. You'd at least get a better idea of where things are breaking down.
Reply with quote
geniusclown
Magician


Joined: 23 Apr 2003
Posts: 358
Location: USA

PostPosted: Thu Sep 01, 2011 10:32 pm   
 
...and a very good suggestion it is. I've rewritten all active scripts to avoid the %concat function and still get that error. Said rewrites were much less efficient and had other bugs so I returned to this code.
_________________
.geniusclown
Reply with quote
geniusclown
Magician


Joined: 23 Apr 2003
Posts: 358
Location: USA

PostPosted: Fri Sep 02, 2011 12:46 am   
 
I've been playing with debugger and learning how to work it. I still don't get why I deselecting a single setting in the tree makes the debugger stop running, but it's not so utterly useless to me anymore. From what I though was an unrelated bug, I tracked down what I think may be the cause:
Code:
<trigger name="queueTick" type="Expression" priority="5" trigontrig="false" newline="false" id="44">
  <pattern>@/core/roundtimer/rt=0 and (%numitems(@/core/queue/queue) or %numitems(@/core/queue/loop))</pattern>
  <value>#ECHO queue: %numitems(@/core/queue/queue) loop: %numitems(@/core/queue/loop)
#SECTION queueTick {
#T- queueTick
#IF (@/core/queue/queue) {
  /core/queue/queueExec=%pop(queue)
  } {
  /core/queue/queueExec=%item(@/core/queue/loop,1)
  /core/queue/loop=%additem(%pop(/core/queue/loop),@/core/queue/loop)
  }
#EXEC @/core/queue/queueExec
#T+ queueTock
}</value>
</trigger>


This trigger is firing when nothing is in @queue or @loop, when it should not. Since the code %pop's @queue if it's got anything, else it cycles @loop... if there's nothing, it tries to cycle @loop, but there's nothing to cycle. It will fire another expression trigger I created to trouble-shoot, #TR {%numitems(@loop)=1 and %len(@loop)=0}. The first line #ECHO verifies that both variables are empty. I added "#IF (%numitems(@queue) or %numitems(@loop)) {" to the very beginning with a matching "}" at the very end, and it seems to have stabilized. Knock on wood.

So, why would the trigger ((@rt=0) and (@queue or @loop)) fire whenever rt=0 regardless of the status of @queue or @loop? I have rewritten the expression trigger several ways with the same results (and worse). Among what I tried,
Code:
(@rt=0) and (%numitems(@queue|loop))
(@rt=0)&(%eval(%len(@queue)+%len(@loop)))
(!@rt)&(@queue || @loop)
_________________
.geniusclown
Reply with quote
geniusclown
Magician


Joined: 23 Apr 2003
Posts: 358
Location: USA

PostPosted: Fri Sep 02, 2011 1:56 pm   
 
With the change above (using #SECTION and adding the #IF statement in trigger queueTick), the program has been much much more stable. But it still locks up, so this isn't the only problem. I'm still seeking a solution.
_________________
.geniusclown
Reply with quote
Display posts from previous:   
Post new topic   Reply to topic     Home » Forums » CMUD General Discussion 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