Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Server gets into infinite loop on certain code #1483

Open
TimLethbridge opened this issue Jul 30, 2019 · 8 comments

Comments

@TimLethbridge
Copy link
Member

commented Jul 30, 2019

In the following code, Umple gets into an infinite loop.

class TreasureChest {
  

  static void report(String message) {
System.out.println(message);
}

  static void scenarioHeader(String message) {
report("\n"+message);
report("------------------------------".substring(1,message.length()));
}

  String getDescription() {
return "The old treasure chest is " + chestStatus() + ".";
}
 
}


statemachine chestStatus{
  
  open{
    String chestStatus() {return "chest open";}
  }
  
  close{
  }

}//$?[End_of_model]$?

class TreasureChest
{
  position 50 30 109 45;
}

class TreasureChest
{
  position 50 30 109 45;
}


@TimLethbridge

This comment has been minimized.

Copy link
Member Author

commented Jul 31, 2019

Other cases of this are coming up.

It seems the problem relates to standalone state machines (a rarely used feature) being defined with a state dependent method. In the above code, the user is not even arranging for the standalone state machine to be used. The correct code should have the statemachine in the class. Then the state dependent methods work.

The key is that we need to trap the infinite loop

@fjtheknight

This comment has been minimized.

Copy link
Contributor

commented Jul 31, 2019

@TimLethbridge

On my machine, Umple takes about 8 seconds to parse the code, and then a loading animation is shown in the diagram pane for 14 seconds and then an error message appears in the diagram pane: "Diagram is out of synchronization with the text due to selecting Manual Sync or an error in the text that has caused the compiler to produce no output."

In cruise.eecs.uottawa.ca/umpleonline/, it takes 20 seconds to parse the code and 35 seconds for the rest. So we can assume that there is no infinite loop?(I noticed that it is really slow right now even when just loading some example it would take several seconds)

The problem comes from the code of the state machine.
statemachine chestStatus{...}

Although umple treats "statemachine" as a key word, I couldn't find it in the grammar files, but found "stateMachine" instead. Also, the umple class for state machines is "StateMachine". So I am not sure why "statemachine" is highlighted in blue.

The other problem is that I couldn't find any example with a state machine declared the same way as in the code above. According to the user manual, shouldn't the code above instead be:

class TreasureChest {
  

  static void report(String message) {
System.out.println(message);
}

  static void scenarioHeader(String message) {
report("\n"+message);
report("------------------------------".substring(1,message.length()));
}

  String getDescription() {
return "The old treasure chest is " + chestStatus() + ".";
}
 
  chestStatus{
  
  open{
    String chestStatus() {return "chest open";}
  }
  
  close{
  }

}
   
}

which works perfectly.

@TimLethbridge

This comment has been minimized.

Copy link
Member Author

commented Jul 31, 2019

@TimLethbridge

This comment has been minimized.

Copy link
Member Author

commented Jul 31, 2019

@TimLethbridge

This comment has been minimized.

Copy link
Member Author

commented Aug 2, 2019

Here is another example:

class TreasureChest {
static void report(String message) {
  System.out.println(message);
}
static void scenarioHeader(String message) {
  report("\n"+message);
  report("------------------------------".substring(1,message.length()));
}
String getDescription() {
  return "The old treasure chest is " + chestStatus() + ".";
}
}


statemachine PersonState {
Sleeping {
String personStatus() {return "sleeping";}
wakeUp -> Awake;
}
Awake {
String personStatus() {return "out and about";}
entry / {report("What a nice morning!");}
goToBed / {report("What a day!");} -> Sleeping;
exit / {report("Time to rest.");}
}
}
@fjtheknight

This comment has been minimized.

Copy link
Contributor

commented Aug 2, 2019

@TimLethbridge

I found the infinite loop: (UmpleInternalParser_CodeStateMachine.ump line 1992)

  private void analyzeStateDependentMethod(Token methodToken, State fromState){
    StateMachine sm = fromState.getStateMachine();
    
    // Make sure we retrieve the same Umple class for nested children as well
    UmpleClass uClass = null;
    StateMachine smRunner = sm;
    while (uClass == null)
    {
      uClass = smRunner.getUmpleClass();
      if (smRunner.getParentState() != null)
    	  smRunner = smRunner.getParentState().getStateMachine();
    }
...

So the problem is that after Umple analyzes state methods, it needs a class where to save those methods. So the method above keeps looking for the class associated with the token. This woks when we have the sm inside the class. However, standalone state machines are not associated with a class, so getUmpleClass() will always return null and this causes the infinite loop.

Fixing this issue seemed a bit complicated (currently state machines are added to the classes as enums, so we need a way to detect classes that use the standalone sm in order to add it to those classes). So I thought why would we use standalone sm? With the example above, maybe we need to create a sm that we want to use for different chests (IronChest, GoldenChest...) so that instead of writing the code for the sm inside every chest class, we can use a standalone sm.

But in that case, wouldn't making a parent Chest class with the sm and use Inheritance solve the issue? Something like:

class Chest {
  String getDescription() {
return "The old treasure chest is " + chestStatus() + ".";
}
chestStatus{
  open{
    String chestStatus() {return "chest open";}
  }
  close{
  }
 }
}

class IronChest {
 isA Chest; 
}

class GoldenChest {
 isA Chest; 
}

Or are there any other cases where using standalone sm is better than having sm inside a class?

@TimLethbridge

This comment has been minimized.

Copy link
Member Author

commented Aug 2, 2019

@TimLethbridge

This comment has been minimized.

Copy link
Member Author

commented Aug 12, 2019

This issue has a fix that is sufficent because the use of standalone state machines with state dependent methods is rare and there is a good workaround (traits). So I am leaving a deeper fix for this (i.e. enabling state-dependent methods in standalone state machines) to later and giving it very low priority

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
2 participants
You can’t perform that action at this time.