mögliches Memory-Leak in iowarrior.(k)o unter Linux ???

Dies ist das deutsche Forum für alle Themen um den IO-Warrior. Beiträge bitte nur in Deutsch.

Moderator: Guido Körber

Post Reply
gm
Posts: 3
Joined: Sat Apr 09, 2005 7:58 pm
Contact:

mögliches Memory-Leak in iowarrior.(k)o unter Linux ???

Post by gm »

Hallo zusammen,

im Forum von codemercs.de bin ich auf einen Artikel aufmerksam geworden, in dem Wayoda schreibt, daß der Treiber für Linux mit vielen Fehlern behaftet ist. Der Kernelabsturz beim Ziehen des Steckers wurde von Codemercs mittlerweile ja behoben, aber irgendwie scheint es ein Kernel-Momory-Leak zu geben sobald ich den IOW40 unter Linux im Betrieb habe. Dieses Leak macht sich nicht sofort bemerkbar, es scheint eher ein schleichender Prozess zu sein - nach 14 Tagen uptime sind ca. 700 MB Hauptspeicher weg (free +/- Buffers). Wenn ich alle Programme aus dem Userspace zusammenrechne, komme ich auf ca. 160 MB, der Rest dürfte daher irgendwo im Kernel verbleiben. Dieses Problem besteht bei mir sowohl mit dem Kernel 2.4.21 (SuSE) bzw. 2.4.26 (vanilla) als auch mit dem 2.6.8.1 (SuSE) oder 2.6.11 (vanilla).
Ist jemanden dahingehend etwas bekannt?

Achja sollte vielleicht noch kurz erklären für was ich den IOW40-Baustein überhaupt verwende: Vom IO-Warrior benutze ich nur den I2C-Bus über den ein DS1621 von Dallas Semiconductor (I2C Temperatursensor) angesteuert wird. Die Temperaturmesswerte werden in eine MySQL-Datenbank weggespeichert, wo sie dann für Auswertungen genutzt werden können.

Viele Grüße gm

Anbei noch der Output von
lsmod :
Module Size Used by
nls_utf8 2176 0
iowarrior 10500 0
fcpci 501912 3
evdev 9216 0

und free:
total used free shared buffers cached
Mem: 773448 767204 6244 0 6948 86128
-/+ buffers/cache: 674128 99320
Swap: 2273188 91996 2181192
wayoda
Posts: 362
Joined: Fri Dec 19, 2003 12:00 pm
Location: Wuppertal/Germany

Post by wayoda »

Ein Kernel-Memory-Leak im IOWarrior-modul in der Größe von
sizeof(struct urb) (92 byte bei kernel 2.6.8, wobei ein struct urb noch einige Zeiger enthält deren Speicherbereich möglicherweise ebenfalls nicht freigegeben wird)
ergibt sich bei jedem Öffnen und Schließen eines iowarrior (nähere Erläuterung siehe unten).
Falls die beschriebene Applikation den IOWarrior40 also nur einmal öffnet und dann auch für die ganze Zeit offen hält (bis reboot oder disconnect), kann dies zumindest nicht der Grund für das Problem sein. Wenn das Programm aber etwa so funktioniert:

Code: Select all

while(true) {
  open;
  lies_den_messwert;
  close;
}
käme es darauf an, wie oft die Schleife läuft.

Eberhard

P.S. Fehlerbeschreibung
Hier gibt es ein Speicherleck bzgl. des URB's (dev->int_in_urb).
Der int_in_urb wird in iowarrior_open() erzeugt, also wenn ein Prozess das Device öffnet. Beim Schließen in iowarrior_release() wird der URB zwar per usb_unlink_urb() aus dem USB-core eintfernt, aber der Speicher für den URB wird nicht freigegeben. Dies geschieht erst in iowarrior_delete(), also entweder nach einem disconnect des IOWarrior oder dem Herunterfahren des Rechners.

Als Folge wird also bei jedem Aufruf von iowarrior_open() der Speicher für einen neuen URB alloziert, aber dieser Speicherbereich wird nicht wieder freigegeben, da usb_free_urb(dev->int_in_urb) eben nur in iowarrior_delete() ausgeführt wird.
Und in iowarrior_delete() wird auch nur der letzte allozierte URB wieder freigegeben.
Das Programm-Fragment:

Code: Select all

int main (int argc, char **argv) {
	int fd1 = -1;
	int i=0;
	for(i=0;i<4;i++) {
		if(( fd1 = open( "/dev/usb/iowarrior0", O_RDWR)) < 0 )	{
			perror( "iowarrior1 open" );
			exit( 1	);
		}
		close( fd1 );
	}
	exit( 0 );
}
erzeugt also 3 schöne kleine Speicherlöcher in der Größe eines URB, die bis zum nächsten reboot erhalten bleiben.

Als Konsequenz würde ich empfehlen, den Aufruf von usb_free_urb(dev->int_in_urb) in iowarrior_release() zu machen:

Also statt :

Code: Select all

/* shutdown any reads that might be going on */
usb_unlink_urb( dev->int_in_urb );
--dev->opened;
if( !dev->present && !dev->opened ) {
	/* the device was unplugged before the file was released */
	up( &dev->sem );
	iowarrior_delete( dev );
	return 0;
}
...lieber so :

Code: Select all

/* shutdown any reads that might be going on */
usb_unlink_urb( dev->int_in_urb );
usb_free_urb(dev->int_in_urb);
dev->opened=0;	//we're closed now
if( !dev->present && !dev->opened ) {
	/* the device is already disconnected, clean up right now */
	up( &dev->sem );
	iowarrior_delete( dev );
	return 0;
}
und natürlich muß dann der Aufruf von usb_free_urb() in iowarrior_delete() entfernt werden.
gm
Posts: 3
Joined: Sat Apr 09, 2005 7:58 pm
Contact:

Post by gm »

Stimmt, meine Anwendung öffnet das Device immer nur extrem kurz, setzt ein Kommando per ioctl ab und schließt es gleich wieder. Dies ist noch ein Relikt aus der Zeit, wo der ganze Kernel abstürtzte, wenn das Gerät abgezogen wurde während es geöffnet war.

Deinen Patch für das Kernelmodul werde ich gleich mal ausprobieren. Schon gleich mal im Voraus vielen Dank für Deine Hilfe!!!

Viele Grüße
Gerhard Massenbichler

PS: Nun sollte es auch wieder mit etwas mehr Uptime klappen, wenn nicht gerade wieder Sicherheitspatches anstehen :-)
Post Reply