Some EventId stops running

62 views
Skip to first unread message

Ricardo

unread,
Dec 30, 2014, 4:38:28 PM12/30/14
to ns-3-...@googlegroups.com
Hi,

I have some classes:
class Neighbor
{
public:
 
// Constructor, other fields and methods

 
~Neighbor ()
 
{
   
if (m_event.IsRunning ())
     
{
       
Simulator::Cancel (m_event);
     
}
   
Simulator::Remove (m_event);
 
}

  Time
  GetExpireTime () const
  {
    return m_expire - Simulator::Now ();
  }

  void
  SetExpireTime (Time exp)
  {
    m_expire = exp + Simulator::Now ();
  }

  template <typename MEM_PTR, typename OBJ_PTR>
  bool
  Schedule (Time delay, bool reset, MEM_PTR memPtr, OBJ_PTR objPtr)
  {
    if (m_event.IsRunning () == true && reset == false)
        return false;

    if (m_event.IsRunning () == true && reset == true)
        Simulator::Cancel (m_event);

    m_event = EventId (); // Tried with and without this line
    m_event = Simulator::Schedule (delay, memPtr, objPtr, m_ip);

    SetExpireTime (delay);
// To store the time when it should be executed. This because sometimes it stops running.

    return true;
  }
private:
 
Ipv4Address m_ip;
 
EventId m_event;
 
Time m_expire;
};

class NeighborList
{
public:
  // Constructor, other fields and methods

  /*
  * I made this method to reschedule every neighbor whose EventId stopped running.
  */
  template <typename MEM_PTR, typename OBJ_PTR>
  bool
  ScheduleNeighbor (const Ipv4Address neighbor, Time delay,
                    MEM_PTR memPtr, OBJ_PTR objPtr)
  {
    for (
std::vector<Neighbor>::iterator it = m_list.begin ();
            it != m_list.end (); ++it)
      {
        if (it->GetIpv4Address () == neighbor)
          {
            it->
Schedule (delay, true, memPtr, objPtr);
            return true;
          }
      }
    return false;
  }

  /*
  * I made this method to reschedule every neighbor whose EventId stopped running.
  */
  template <typename MEM_PTR, typename OBJ_PTR>
  void
  RescheduleFailed (MEM_PTR memPtr, OBJ_PTR objPtr)
  {
    for (
std::vector<Neighbor>::iterator it = m_list.begin ();
            it != m_list.end (); ++it)
      {
        if (it->m_event.IsExpired () && Simulator::GetDelayLeft (it->m_event) <= Seconds (0))
          {
            if (it->GetExpireTime () > MilliSeconds (0))
              {
                it->ScheduleNeighborExpireTimer (it->GetExpireTime (), true, memPtr, objPtr);
              }
            else
              {
                it->ScheduleNeighborExpireTimer (MilliSeconds (100), true, memPtr, objPtr);
              }
          }
      }
  }
private:
 
Ipv4Address m_id;
 
std::vector<Neighbor> m_list;
};


This is the basic code, from my RoutingProtocol when I receive HELLOs I update the NeighborList. But sometimes the EventId stop running and don't expire, and so they don't execute the code they should call. This without notice.

I have lots of messages to help me debug. And this way I noticed it.

This doesn't happen always, just sometimes. So I made the RescheduleFailed method, but even the rescheduling doesn't work. The EventIds that are rescheduled stop running and don't execute the code they should.

I don't know why, any help is appreciated.

Thanks, and happy holidays :)

Tommaso Pecorella

unread,
Dec 30, 2014, 5:06:43 PM12/30/14
to ns-3-...@googlegroups.com
Hi,

I had similar issues once, and it turned out that the scheduler was fine.
Believe me, the ns-3scheduler is one of the most tested and stressed things, and the probability that a scheduled event isn't executed are... extremely low. So low that I'm ready to bet a couple bucks.

I'd first try to see if you have a nasty memory bug. It is what was messing with my code. Use valgrind and see if you have memory leaks or containers (vectors and such) going out of range.
Next, check that the pointers you are using in the schedule function are valid at the moment of the event execution, nobody can guarantee about that, unless they're Smart Pointers.
Summarising, I'd search the bug elsewhere.

Hope this helps,

T.


On Tuesday, December 30, 2014 10:38:28 PM UTC+1, Ricardo wrote:
Hi,

I have some classes:


Ricardo

unread,
Jan 9, 2015, 3:16:30 AM1/9/15
to ns-3-...@googlegroups.com
Hi, I solved the issue.

I post this so anyone who reads it learns from my experience.

I read in some question about Timers a comment from Tommaso that he uses EventId instead of Timers. So I changed from Timers to EventId. But I had in the code a destructor to stop the Timer, when I made the change I didn't changed the destructor, I thought it would work in the same way. The code is something like this:
class Neighbor
{
private:
 
EventId m_event;
 
// more fields
public:
 
// Constructor
 
~Neighbor ()

 
{
   
if (m_event.IsRunning ())
     
{
       
Simulator::Cancel (m_event);
     
}
   
Simulator::Remove (m_event);
 
}

 
// More methods
}

The Neighbor instances are stored in a vector<Neighbor> in other class that I use in the the routing protocol class. My thinking about it was: when I delete the neighbor from the vector the destructor is called and the EventId is stopped. But as it turns out, the destructor is used also when I referenced this instances for other uses. And so the EventId was being (very) wrongly stopped. A pretty basic and awkward mistake, I know :(

So to fix it I removed the destructor and in the method to delete Neighbors from the vector I made sure (I double check) that the event is stopped. Now it's working like a charm :)

And the issue with the timers (the one that forced me to change to EventId) I'll never know, maybe something similar. The timers some times they worked, and the other times the program stopped with a SIGSEV.

Tommaso, thank you for your quick answer, I never answered until know.
Reply all
Reply to author
Forward
0 new messages