symphonytool / symphony

The Symphony IDE
5 stars 4 forks source link

Interpreter: Exception in thread Main, Serializable #268

Closed JeremyBryans closed 10 years ago

JeremyBryans commented 10 years ago

In the model Jeremy.cml, following the trace [init.1, init.2, init.3, on.1, on.2, on.3, n_req.1, out.mk_MSG(1, 1, nil)] an "exception in thread main" is reported (in red, so it must be important ;

I've emailed the file to Joey and Kennet.

joey-coleman commented 10 years ago

Adding the file here:

-- add chan to output state of MessageStore?
-- add chan to output "I am leader"

types

  NODE = nat1

  ALLNODES = set of nat1

  CLAIM = <leader>|<follower>|<undecided>|<off>

  DATA = token

  CS :: c : CLAIM
        s : STRENGTH

-- The only messages transmitted are CS messages, so MSG can be specialised to them  
  MSG :: src : NODE
         dest : NODE
         cs : [CS]

  STRENGTH = nat

values

  allNodes : set of nat1 = {1,...,3}

  ulp : nat = 10

  n_timeout : nat = 4     -- the timeout value employed by the Nodes

channels
   inn : MSG
   out : MSG     
   n_req : NODE    

   test : set of MSG

process MessageStore =
begin 
  state
    store : set of MSG := {}
  functions
   selectMSG(sm : set of MSG) r:MSG
    pre sm <> {}
    post r in set sm

  operations

  add:(MSG) ==> ()
  add(m) ==
   store := store union {m}

-- fetchFor fetchs all messages in the store that are for the node n

  fetchFor:(NODE) ==> MSG
  fetchFor(n) ==
  (
  dcl m : MSG @ 
   (
    dcl s : set of MSG @ s := {msg|msg in set store @ msg.dest = n}; 
    (
    if s <> {} 
    then (m := selectMSG(s); store := store \ {m})  
    else m := mk_MSG(n,n,nil)
    ); return m
   )
  ) 

-- don't think this will work: too difficult to select a single element from a set 

  fetchOne:(NODE) ==> MSG
  fetchOne(n) ==
  let msgs = {msg|msg in set store @msg.dest=n} in
   (if msgs <> {} then 
     let m = select(msgs) in 
     ( store := store\{m};
        return m
     )   
    else 
     return mk_MSG(n,n,nil)
   )

  -- helper function; selects an "arbitrary" element from a non-empty set  
  select(sn : set of MSG) r: MSG
  pre sn <> {}
  post r in set sn      

  actions
    In = inn?m -> add(m); Skip  
    Listen = [] i in set allNodes @ n_req.i -> (dcl m : MSG @ m := fetchOne(i);out!m->Skip)
    Test = test!store -> Skip
    Loop =  (In [] Listen [] Test);Loop
    @
     Loop
end          

channels 
  on, off : nat1
  init : nat1

-- test channels
  leading : nat1
  following : nat1

process Node = i : nat1 @

begin 

state

    -- mem is volatile memory
    mem: map NODE to [CS] := { cid |-> nil | cid in set allNodes \ {i} }                -- the map of node ids to their CSs,  using mk_CS(<off>, 0) instead of nil
     inv dom mem = allNodes  \ {i} and -- the domain of mem must not include id (the ID of the node)
         dom mem <> {}                  -- must be more than one node in the network  (although this model 
                                        -- should work if there is only one node)

    -- below are summary variables  
    highest_strength : [STRENGTH] := nil                   -- the highest strength of leadership claim node is aware of         

    highest_strength_id : [NODE] := nil                 -- id of node making the leadership claim with the highest strength
                                                       -- this is allowed to be any node id, including id itself

    inv highest_strength_id <> nil => highest_strength_id in set (dom mem union {i}) 

    leaders : nat := 0                                 -- the leader count among my neighbours; nat, so can't be -1 in CML
    inv leaders <= card dom mem

    myCS : CS := mk_CS(<off>, 0)                                     -- my claim/strength pair

    myNeighbours : seq of NODE := [j| j in set dom mem @ j <>i]

    isleader : bool := false

operations

  Init: () ==> ()
    Init() ==
    (
      flushState() -- flush volatile and summary memory
    )

    flushState: () ==> ()
    flushState() ==
    (
      flushMemory();
      flushSummary()
    )

    flushMemory: () ==> ()
    flushMemory() ==
     (
      mem := { cid |-> nil | cid in set allNodes \ {i} } -- reset
     )

    flushSummary: () ==> ()
    flushSummary() ==
    ( 
      highest_strength := 0; 
      highest_strength_id := nil; 
      leaders := 0;                -- can't be -1 if nat :: could be nil
      myCS := mk_CS(<off>, 0);
      isleader := false
    )

    -- used by controller to write a CS to a memory cell

    write: MSG ==> ()
    write(m) ==
    ( 
     mem(m.src) := m.cs
    )
    pre m.src in set dom mem
    post mem(m.src) = m.cs

    update:()==>()
    update() == 
    (
      leaders := card{n|n in set dom mem @ mem(n)<>nil => mem(n).c = <leader>};
      highest_strength := maxStrength();                
      highest_strength_id := maxStrengthID();                     
      isleader := amILeader()    
    )  
    post isleader or 
         (leaders > 0 and /* highest_strength_id <> nil => */ mem(highest_strength_id).s = highest_strength)

    -- maxStrengh returns the maximum strength of leadership claim

  maxStrength:() ==> [nat]
    maxStrength() == 
    (
     let leaderNodes = {n|n in set dom mem @ mem(n) <> nil and mem(n).c = <leader>} in
     (     
      let strs = {mem(l).s|l in set leaderNodes} in 
       if strs <> {} 
       then return maxSet(strs) 
       else return nil  
     )
    )    

/*
    maxStrength:() ==> [nat]
    maxStrength() == 
    (
     dcl leaderNodes : set of nat1 @ leaderNodes := {n|n in set dom mem @ mem(n) <> nil and mem(n).c = <leader>};
     (     
      dcl strs : set of nat @ strs := {mem(l).s|l in set leaderNodes}; 
      if strs <> {} then return maxSet(strs) --  maxSet(strs)
      else return nil  
     )
    )    
*/       
   -- return the ID of the leader with the max strength
   -- or nil if no leader claims

    maxStrengthID : () ==> [NODE]
    maxStrengthID() ==  
    (
      let leaderNodes = {n|n in set dom mem @ mem(n) <> nil and mem(n).c = <leader>} in 
      (
       dcl maxStrIds : set of NODE @ 
        (
         if leaderNodes = {} 
         then return nil 
         else maxStrIds := {n | n in set leaderNodes @ mem(n).s = highest_strength};
              return select(maxStrIds) 
        )
       ) 
    )   

 /*  
    maxStrengthID : () ==> [NODE]
    maxStrengthID() ==  
    (
      dcl leaderNodes : set of nat1 @ leaderNodes := {n|n in set dom mem @ mem(n) <> nil and mem(n).c = <leader>};
      (
       dcl maxStrIds : set of NODE @ 
        (
         if leaderNodes = {} 
         then return nil 
         else maxStrIds := {n | n in set leaderNodes @ mem(n).s = highest_strength};
              return select(maxStrIds) 
        )
       ) 
    )   
*/

    -- update my claim 
    -- note that we can enforce state transitions through the changeClaim operation
    -- since Claim corresponds directly to the states in the ST diagram

    changeClaim: CLAIM ==> ()
    changeClaim(newc) ==
    ( 
      dcl currStr : STRENGTH := myCS.s @ 
      myCS := mk_CS(newc, currStr)
    )
    pre myCS.c = <off> => newc = <undecided> and
        myCS.c = <undecided> => newc = <leader> or newc = <follower> and
        myCS.c = <leader> => newc = <undecided> and
        myCS.c = <follower> => newc = <undecided>

    -- increase the strength of my claim up to the maximum (upper limit of petitions: ulp)
    incStrength:()==>()
    incStrength() ==
    (
      if myCS.s < ulp                    
      then myCS := mk_CS(myCS.c, myCS.s+1)
    )
    pre myCS.s < ulp
    post myCS.s = myCS~.s + 1

    amILeader: () ==> bool
    amILeader() ==  
    (
      return (leaders = 0)  or
             (highest_strength = nil) or  
             (highest_strength <> nil and highest_strength < myCS.s) or 
             (highest_strength <> nil and highest_strength = myCS.s and highest_strength_id < i) 
    )

    maxSet: set of nat ==> nat
    maxSet(sn) ==
     (dcl s: set of nat @ s:= sn;
      (dcl c:nat @ c := select(s); 
         s := s \ {c};
         while (s <> {}) do
          (dcl n:nat @ n := select(s);
           if (n>c) then c:=n else c:=c;
           s := s\{n}
          ); 
        return c
        )
      )
      pre sn <> {}
--      post c in set sn and forall s in set sn @ c >=s

  functions

      -- implicit helper function; selects an element of a non-empty set  
      select(sn : set of nat) r: nat
      pre sn <> {}
      post r in set sn 

  actions 

    Listener = ReceiveData;update(); Skip

    -- Asks for data via n_rec, then receives it, then repeats

    ReceiveData = 
     n_req!i -> 
       out?msg ->
       (
        [msg.cs = nil] & Skip
        [] 
        [msg.cs <> nil] & write(msg);ReceiveData
       ) 
--        [_ n_timeout _> Skip

    SendCS =  (||| t in set dom mem @ [{}] inn!mk_MSG(i,t,myCS) -> Skip) -- insists on sending all messages before it progresses.

    Off = on!i -> (Undecided /_\ off!i -> flushState();Off)  

    Undecided = changeClaim(<undecided>);Listener;
               (
                [isleader] & Leader
                [] 
                [not isleader] & Follower
               )             

    Leader = changeClaim(<leader>);SendCS; leading.i -> Listener;

             (
              [not isleader] & Undecided  
              []
              [isleader] & incStrength();Leader
             )                    

    Follower = changeClaim(<follower>);flushMemory(); following.i -> SendCS; Listener; -- flushing primary memory; self-declare as a follower
               (                                                
                [leaders <> 1] & Undecided 
                []
                [leaders = 1] & Follower                      
               )             

  @ init.i -> Init();Off

end

process AllNodes = ||| i in set allNodes @  (Node(i)) 

process Election = AllNodes [|{|inn,out,n_req|}|] MessageStore
lausdahl commented 10 years ago

The problem is the deepCopy-clone that's made for one of the parallel constructs. The stack runs down ProcessObjectValues and eventually hits a base Context which includes a non-serilizable field ThreadState

lausdahl commented 10 years ago

A fix for this in Overture is in overturetool/overture@5d6025b4badf4e51dcbb12e766b3cba0e121e23f

JeremyBryans commented 10 years ago

Hi Kennet,

Thank you. The link you posted 404'd; could you resend?

J

joey-coleman commented 10 years ago

That's a commit link — we'll have a build of it later today most likely

joey-coleman commented 10 years ago

There is a new development build that should incorporate the fix for this.

joey-coleman commented 10 years ago

Reopening: Jeremy found another case where it happens. Use trace: <tock, tock>.

The code is a bit long; exception trace follows.

-- add chan to output state of MessageStore?
-- add chan to output "I am leader"

-- uses of dcl are replaced by let...in where possible.
-- otherwise, temporary variable are used

values 

   debugS = false    --debug Store
   debugMem = false -- true
   debugCS = false -- true
   debugR = false -- true  --debug Rest

  allNodes : set of nat = {1,...,3}

  uls : nat = 10

  n_timeout : nat = 1     -- the timeout value employed by the Nodes

types

  NODE = nat
   inv n == n in set allNodes

  CLAIM = <leader>|<follower>|<undecided>|<off>|<TEST>
  STRENGTH = nat

  CS :: c : CLAIM
    s : STRENGTH

-- The only messages transmitted are CS messages, so MSG can be specialised to them  
  MSG :: src : NODE
         dest : NODE
         cs : CS 

channels
   inn : NODE * NODE * MSG     -- SRC * DEST * MSG
   out : NODE * NODE * MSG     -- DEST * SRC * MSG

   debugStore : map NODE to seq of MSG
   debugKey : NODE
   debugTail, debugStoreI : seq of MSG

process MessageStore =
begin 
  state
   store : map NODE to seq of MSG := {i|->[]|i in set allNodes}

  operations

    RmvHdFrmStore:NODE ==> ()
    RmvHdFrmStore(i) ==
     store := store ++ {i |-> tl(store(i))}
    pre store(i) <> []

-- temp back in  functions

/*      -- implicit helper function; selects an element of a non-empty set  
      select(sn : set of nat) r: nat
      pre sn <> {}
      post r in set sn 
*/       

  actions

   DebugState = i : nat @ 
    if debugS then 
     debugStore!store ->
       debugStoreI!(store(i)) -> 
         debugKey!i -> 
           debugTail!(tl(store(i))) -> Skip
    else 
     Skip

    Loop =  
     inn?src?des?m -> store(m.dest) := store(m.dest)^[m]; Skip  
      []
      ([] i in set allNodes @ 
        [store(i) <> []] &  -- there are messages for node i    
           let m = hd(store(i)) in
           out!(m.dest)!(m.src)!m -> 
                RmvHdFrmStore(i);
                  Skip)

    @ while true do Loop
end          

channels 
  on, off,init : nat1

-- test channels
  leading : nat1
  following : nat1
  undecided : nat1

  DebugLeaders : NODE * nat * nat
  DebugHighestStrength : NODE * nat * [STRENGTH] 
  DebugHighestStrengthID : NODE * nat * [NODE]
  DebugIsLeader : NODE *  nat *bool
  DebugMem : NODE * nat * map NODE to [CS]
  DebugClaim : NODE * nat * CS

  DebugClaimBeforeL : NODE * CS
  DebugClaimAfterL : NODE * CS

  DebugStrength : NODE * STRENGTH

process Node = i : nat1 @

begin 

state

    mem: map NODE to [CS] := { cid |-> nil | cid in set allNodes \ {i} }        
     inv dom mem = allNodes  \ {i} and -- the domain of mem must not include id (the ID of the node)
         dom mem <> {}                  -- must be more than one node in the network  (although this model 
                                        -- should work if there is only one node)

    -- below are summary variables  
    highest_strength : [STRENGTH] := nil                   -- the highest strength of leadership claim node is aware of         

    highest_strength_id : [NODE] := nil                 -- id of node making the leadership claim with the highest strength
                                                       -- this is allowed to be any node id, including id itself

    inv highest_strength_id <> nil => highest_strength_id in set (dom mem union {i}) 

    leaders : nat := 0                                 -- the leader count among my neighbours
    inv leaders <= card dom mem

    myCS : CS := mk_CS(<off>, 0)                                     -- my claim/strength pair

    isleader : bool := false

   -- temp variables s,c created here while maxSet cannot use dcl to create them.

   s : set of nat 
   c : nat

operations

    flushState: () ==> ()
    flushState() ==
     (
      flushMemory();flushSummary()
     )

    flushMemory: () ==> ()
    flushMemory() ==
       (
        mem := { cid |-> nil | cid in set allNodes \ {i} } 
       )

    flushSummary: () ==> ()
    flushSummary() ==
    ( 
      highest_strength := nil; --0;
      highest_strength_id := nil; 
      leaders := 0;                
      myCS := mk_CS(<off>, 0);
      isleader := false
    )

    write: NODE * MSG ==> ()
    write(j,m) ==
    ( 
     mem := mem ++ {j |-> m.cs}
    )     
    pre j in set dom mem
    post mem(j) = m.cs

    update:()==>()
    update() == 
    (  --the leaders count should not increase if mem(c)=nil
      leaders := card{n|n in set dom mem @ mem(n)<>nil and mem(n).c = <leader>};
      highest_strength := maxStrength();                
      highest_strength_id := maxStrengthID()
    )  

--    post isleader or 
--         (leaders > 0 and  mem(highest_strength_id).s = highest_strength)

    -- maxStrengh returns the maximum strength of leadership claim

  maxStrength:() ==> [nat]
    maxStrength() == 
    (
     let leaderNodes = {n|n in set dom mem @ mem(n) <> nil and mem(n).c = <leader>} in
     (    
     if leaderNodes <> {} then 
      let strs = {mem(l).s|l in set leaderNodes} in 
       if strs <> {} 
       then return maxSet(strs) 
       else return nil 
     else return nil   
     )
    )    

   -- return the ID of the leader with the max strength
   -- or nil if no leader claims

maxStrengthID : () ==> [NODE]
    maxStrengthID() ==  
    (
      let leaderNodes = {n|n in set dom mem @ mem(n) <> nil and mem(n).c = <leader>} in 
      (
       if leaderNodes = {} 
       then return nil 
       else 
         let maxStrIds = {n | n in set leaderNodes @ mem(n).s = highest_strength} in 
         -- return select(maxStrIds) -- select is wrong here; has to pixk the maximum one!!
         return maxSet(maxStrIds)
       )
     )   

-- update my claim 
    -- note that we can enforce state transitions through the changeClaim operation
    -- since Claim corresponds directly to the states in the ST diagram

    changeClaim: CLAIM ==> ()
    changeClaim(newc) ==
    ( 
--      if myCS.c = newc then      
--       myCS := mk_CS(newc, myCS.s)  
--      else --reset strength -- could differentiate between leader and follower
--       myCS := mk_CS(newc,0)
         myCS.c := newc
)

/* pre myCS.c = <off> => newc = <undecided> and
    myCS.c = <undecided> => newc = <leader> or newc = <follower> and
        myCS.c = <leader> => newc = <undecided> and
        myCS.c = <follower> => newc = <undecided>
*/

    changeStrength: nat ==> ()
    changeStrength(n) ==
      myCS := mk_CS(myCS.c,n)

    -- increase the strength of my claim up to the maximum (upper limit of petitions: uls)
incStrength:()==>()
incStrength() ==
(
  if myCS.s < uls                    
  then myCS := mk_CS(myCS.c, myCS.s+1)
  else Skip
)

    amILeader: () ==> bool
    amILeader() ==  
    (
      return (leaders = 0)  or
             (highest_strength = nil) or  
             (highest_strength <> nil and highest_strength < myCS.s) or 
             (highest_strength <> nil and highest_strength = myCS.s and highest_strength_id < i) 
    )

  maxSet: set of nat ==> nat
    maxSet(sn) ==
     ( 
--    dcl s:nat @   
          s:= sn;
--      (
--      dcl c:nat @ 
         c := select(s); 
         s := s \ {c};
         while (s <> {}) do
          (let n = select(s) in
             (if (n>c) then c:=n else c:=c;
              s := s\{n})
          ); 
        return c
--        )
      )
      pre sn <> {}

  functions

      -- implicit helper function; selects an element of a non-empty set  
      select(sn : set of nat) r: nat
      pre sn <> {}
      post r in set sn 

  actions 

    Listener = ReceiveData;update();Skip

    Debug = pos : nat @ DebugM(pos);DebugRest(pos);DebugMyCS(pos)

    DebugM =  pos : nat @
    if debugMem then
      DebugMem!i!pos!mem -> Skip
    else 
     Skip

    DebugRest = pos : nat @
    if debugR then  
     DebugLeaders!i!pos!leaders ->
      DebugHighestStrength!i!pos!highest_strength -> 
       DebugHighestStrengthID!i!pos!highest_strength_id -> 
        DebugIsLeader!i!pos!isleader ->
           Skip
     else
      Skip  

    DebugMyCS = pos : nat @
    if debugCS then  
        DebugClaim!i!pos!myCS ->
           Skip
     else
      Skip      

        ReceiveData = 
        (
         out!i?j?msg -> (mem := mem ++ {j |-> msg.cs}); ReceiveData
        ) [_ n_timeout _> Skip

-- The first version of SendCS produces an exception: it is reported as Bug#268; should now be fixed, but doesn't apear to be. 

    SendCS = (||| t in set dom mem @ [{}] inn!i!t!(mk_MSG(i,t,myCS)) -> Skip) -- insists on sending all messages before it progresses.

-- The second version is temporary.
/*       
      SendCS =
       let mycs = myCS in
       ( 
        for all d in set dom mem do
          (
            inn!i!d!(mk_MSG(i,d,mycs)) -> Skip 
          ) 
       )
 */

    Off =  on!i -> (Undecided /_\  off!i -> flushState();Off)  

-- isleader must to be updated separately and directly; otherwise the guards don't work correctly. 

    Undecided = Debug(1);
                   (myCS.c := <undecided>);  
--                 changeClaim(<undecided>);   -- the operation fails; I don't know why. 
                 Debug(2);
                   undecided!i -> Debug(3);Listener;
                 (isleader := amILeader());
                  Debug(4);
               (

[isleader] & Leader
                [] 
                [not isleader] & Follower
               )             

    Leader =  (myCS.c := <leader>);   
    --changeClaim(<leader>);
                   leading.i -> SendCS; Debug(1); 
                     Listener; Debug(2);
                      (isleader := amILeader()); 
                        Debug(3);
             (
              [not isleader] & Undecided  
              []
              [isleader] & incStrength();Leader
             )                    

  Follower = 
  -- changeClaim(<follower>);changeStrength(0); 
    (myCS.c := <follower>);   (myCS.s := 0); 
    following!i ->
  -- Debug(2);
     SendCS; flushMemory();Listener; -- flushing primary memory; then listen
                 (isleader := amILeader());
                --   Debug(2);
               (                                                
                [leaders <> 1] & Undecided 
                []
                [leaders = 1] & Follower                      
               )             

  @ init.i -> flushState();Off

end

process AllNodesSet = ||| i in set allNodes @  (Node(i)) 

process OneNode = Node(1)

process TwoUnconnectedNodes = Node(1) ||| Node(2)

process ThreeNodes = Node(1) ||| Node(2) ||| Node(3)

process TwoProcesses = (TwoUnconnectedNodes [|{|inn,out|}|] MessageStore) \\ {|inn,out|}

process Election = (AllNodesSet [|{|inn,out|}|] MessageStore)  \\ {|inn,out|}

process Election2 = (ThreeNodes [|{|inn,out|}|] MessageStore)  \\ {|inn,out|}

--===testing area===--
channels 
 success, cp1,cp2,cp3,offthree,alloff
chansets 
 allEventsExcOff = {|init,on,undecided,leading,following|}
 allEvents = {|init,on,undecided,leading,following|} union {|off|}
process Tests = i : nat @
 begin 
 actions 

 RunTest = 
   [i=1] & Init;AllOn;Trace1;Success                      -- success after three tocks
   []
   [i=2] & Init;AllOn;Trace2;Success                      -- success after two tocks [off.3, offthree, tock, tock, success]
   []
   [i=3] & Skip;Success                                   -- immediate success 
   []
   [i=4] & Init;AllOn;Trace1;AllOff;AllOn;Trace4;Success  -- success should have [tock, tock, tock, tock, tock, tock, success]
   []
   [i=5] & Init;AllOn;Trace1;Trace5;Success               -- fails
   []
   [i=6] & Trace6;Success

   Init   = init.1 -> init.2 -> init.3 -> Skip
   AllOn  = on.1 -> on.2 -> on.3 -> Skip
   AllOff = off.1 -> off.2 -> off.3 -> Skip
   Success = success -> Skip 

   Trace1 =   undecided.1 -> undecided.2 -> undecided.3 -> 
             leading.1 -> leading.2 -> leading.3 ->              
                leading.3 -> undecided.1 ->  
                   undecided.2 -> 
                    following.1 -> following.2 -> leading.3 -> Skip
   Trace2 = undecided.1 -> undecided.2 -> undecided.3 -> offthree ->
           leading.1 -> leading.2 -> leading.2 -> undecided.1 -> Skip

   Trace4 = undecided.1 -> undecided.2 -> undecided.3 -> off.3 ->
           leading.1 -> leading.2 -> leading.2 -> undecided.1 -> 
             leading.2 -> following.1 -> Skip

Trace6 = Trace1;AllOff;AllOn

   Trace5 = off.3 -> undecided.1 -> undecided.2 -> 
            leading.2 -> following.1 -> leading.2 -> following.1 -> 
              on.3 -> undecided.3 -> leading.2 -> following.1 ->
               leading.2 -> following.1 -> following.3 -> Skip 

  @RunTest
end  

process TestOne   = Election2 [|allEventsExcOff|] Tests(1)    \\ allEventsExcOff
process TestTwo   = Election2 [|allEventsExcOff|] Tests(2)    \\ allEventsExcOff
process TestThree = Election2 [|allEventsExcOff|] Tests(3)    \\ allEventsExcOff
process TestFour  = Election2 [|allEvents|] Tests(4)    \\ allEvents
process TestFive  = Election2 [|allEvents|] Tests(5)    \\ allEvents

Exception trace:

Exception in thread "main" Internal 0005: Illegal clone: java.io.NotSerializableException: eu.compassresearch.core.interpreter.api.values.NoConstraint
    at org.overture.interpreter.values.ObjectValue.deepCopy(ObjectValue.java:469)
    at org.overture.interpreter.runtime.ObjectContext.deepCopy(ObjectContext.java:77)
    at org.overture.interpreter.runtime.ObjectContext.deepCopy(ObjectContext.java:74)
    at org.overture.interpreter.runtime.ObjectContext.deepCopy(ObjectContext.java:74)
    at org.overture.interpreter.runtime.Context.deepCopy(Context.java:156)
    at org.overture.interpreter.runtime.Context.deepCopy(Context.java:156)
    at org.overture.interpreter.runtime.Context.deepCopy(Context.java:156)
    at org.overture.interpreter.runtime.Context.deepCopy(Context.java:156)
    at org.overture.interpreter.runtime.Context.deepCopy(Context.java:156)
    at org.overture.interpreter.runtime.Context.deepCopy(Context.java:156)
    at org.overture.interpreter.runtime.Context.deepCopy(Context.java:156)
    at org.overture.interpreter.runtime.Context.deepCopy(Context.java:156)
    at org.overture.interpreter.runtime.Context.deepCopy(Context.java:156)
    at eu.compassresearch.core.interpreter.runtime.DelayedWriteContext.deepCopy(DelayedWriteContext.java:184)
    at eu.compassresearch.core.interpreter.ActionInspectionVisitor.caseParallelBegin(ActionInspectionVisitor.java:573)
    at eu.compassresearch.core.interpreter.ActionInspectionVisitor.access$000(ActionInspectionVisitor.java:87)
    at eu.compassresearch.core.interpreter.ActionInspectionVisitor$5.execute(ActionInspectionVisitor.java:450)
    at eu.compassresearch.core.interpreter.ConcreteCmlBehaviour.execute(ConcreteCmlBehaviour.java:328)
    at eu.compassresearch.core.interpreter.CommonInspectionVisitor$30.execute(CommonInspectionVisitor.java:1113)
    at eu.compassresearch.core.interpreter.ConcreteCmlBehaviour.execute(ConcreteCmlBehaviour.java:328)
    at eu.compassresearch.core.interpreter.CommonInspectionVisitor.caseParallelNonSync(CommonInspectionVisitor.java:411)
    at eu.compassresearch.core.interpreter.CommonInspectionVisitor$29.execute(CommonInspectionVisitor.java:1064)
    at eu.compassresearch.core.interpreter.ConcreteCmlBehaviour.execute(ConcreteCmlBehaviour.java:328)
    at eu.compassresearch.core.interpreter.CommonInspectionVisitor.caseParallelNonSync(CommonInspectionVisitor.java:414)
    at eu.compassresearch.core.interpreter.ProcessInspectionVisitor$8.execute(ProcessInspectionVisitor.java:346)
    at eu.compassresearch.core.interpreter.ConcreteCmlBehaviour.execute(ConcreteCmlBehaviour.java:328)
    at eu.compassresearch.core.interpreter.CommonInspectionVisitor.caseParallelNonSync(CommonInspectionVisitor.java:414)
    at eu.compassresearch.core.interpreter.ProcessInspectionVisitor$8.execute(ProcessInspectionVisitor.java:346)
    at eu.compassresearch.core.interpreter.ConcreteCmlBehaviour.execute(ConcreteCmlBehaviour.java:328)
    at eu.compassresearch.core.interpreter.CommonInspectionVisitor$9.execute(CommonInspectionVisitor.java:491)
    at eu.compassresearch.core.interpreter.ConcreteCmlBehaviour.execute(ConcreteCmlBehaviour.java:328)
    at eu.compassresearch.core.interpreter.CommonInspectionVisitor$12.execute(CommonInspectionVisitor.java:627)
    at eu.compassresearch.core.interpreter.ConcreteCmlBehaviour.execute(ConcreteCmlBehaviour.java:328)
    at eu.compassresearch.core.interpreter.CommonInspectionVisitor$9.execute(CommonInspectionVisitor.java:491)
    at eu.compassresearch.core.interpreter.ConcreteCmlBehaviour.execute(ConcreteCmlBehaviour.java:328)
    at eu.compassresearch.core.interpreter.CommonInspectionVisitor$12.execute(CommonInspectionVisitor.java:627)
    at eu.compassresearch.core.interpreter.ConcreteCmlBehaviour.execute(ConcreteCmlBehaviour.java:328)
    at eu.compassresearch.core.interpreter.VanillaCmlInterpreter.executeBehaviour(VanillaCmlInterpreter.java:344)
    at eu.compassresearch.core.interpreter.VanillaCmlInterpreter.executeTopProcess(VanillaCmlInterpreter.java:301)
    at eu.compassresearch.core.interpreter.VanillaCmlInterpreter.execute(VanillaCmlInterpreter.java:228)
    at eu.compassresearch.core.interpreter.debug.SocketServerCmlDebugger.start(SocketServerCmlDebugger.java:436)
    at eu.compassresearch.core.interpreter.debug.DebugMain.main(DebugMain.java:208)
JeremyBryans commented 10 years ago

The two tocks occur after debugging on TestFive

joey-coleman commented 10 years ago

Also in TestOne, which is what I had tried.