Hi all.

Eddie, I already mailed this patch to you. For the sake of completeness, I also 
post
this to the list, sorry for the duplication.

There seems to be a problem with the Click timers, which leads to 100% CPU
utilization. It can be reproduced as follows (tested on three x86 machines):

(1) Compile Click with the attached timerdebug element included. I'm not using 
any
    special configure flags, just --enable-local and --disable-linuxmodule.

(2) Start Click with timerdebug.click (also attached).

(3) Start netcat (i.e. 'nc -u 10.0.0.2 5000'), send some data and monitor CPU
    utilization (I used 'top'). For me, 10 to 20 UDP packets were always enough 
to
    trigger this problem.

I'm not sure whether the problem lies in my timerdebug element, but what seems
to fix it, is the attached patch. The incident that triggers the problem begins
in master.cc, at the end of timer_reheapify_from:

        _timer_expiry = Timestamp();

This sets _timer_expiry to zero. Later, in 
master.hh::next_timer_expiry_adjusted(),
if _timer_stride < 8, the value of _timer_expiry is taken, Timer::adjustment()
is subtracted from it and returned, which then has the value:

        e.sec = -1, e.subsec = 999500

Which leads to unintended behavior after the calls to
next_timer_expiry_adjusted() in master.cc, see the if-clauses there. A
timeout/wait value of zero is given to poll/select/kevent, where no timeout
should be used instead.

Nadi

diff --git a/include/click/master.hh b/include/click/master.hh
index 2dcedcf..64e629c 100644
--- a/include/click/master.hh
+++ b/include/click/master.hh
@@ -255,6 +255,8 @@ Master::next_timer_expiry_adjusted() const
     if (_timer_stride >= 8)
 	return _timer_expiry;
     Timestamp e = _timer_expiry;
+    if (e.sec() == 0)
+	return e;
     if (_timer_stride >= 4)
 	e -= Timer::adjustment();
     else
#include <click/config.h>
#include "timerdebug.hh"

CLICK_DECLS

int Timerdebug::initialize (ErrorHandler*)
{
	timer.initialize(this);
	return 0;
}

void Timerdebug::push (int, Packet* p)
{
	if (!timer.scheduled()) {
		click_chatter("starting timer");
		timer.schedule_after_msec(100);
	}
	p->kill();
}

void Timerdebug::run_timer (Timer*)
{
	click_chatter("timer callback");
}

CLICK_ENDDECLS

EXPORT_ELEMENT(Timerdebug)
tun0 :: KernelTun(10.0.0.1/24)
        -> Timerdebug
#ifndef CLICK_TIMERDEBUG_HH
#define CLICK_TIMERDEBUG_HH

#include <click/element.hh>
#include <click/timer.hh>

CLICK_DECLS

class Timerdebug : public Element
{
public:

	Timerdebug (void)
		: Element(), timer(this)
	{};

	const char* class_name (void) const { return "Timerdebug"; }
	const char* port_count (void) const { return PORTS_1_0; }
	const char* processing (void) const { return PUSH; }
	
	int configure (Vector<String> &, ErrorHandler*) { return 0; };
	int initialize (ErrorHandler* errh);

	void push (int, Packet* p);

	Timer timer;
	void run_timer (Timer* timer);
};

CLICK_ENDDECLS

#endif
_______________________________________________
click mailing list
click@amsterdam.lcs.mit.edu
https://amsterdam.lcs.mit.edu/mailman/listinfo/click

Reply via email to