www.mikrocontroller.net

Forum: PC-Programmierung tcdrain() produziert endlosschleife unter linux


Autor: Daniel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,
ich weiß sehr wohl dass ihr mir direkt nur weiterhelfen könnt wenn ihr 
den Code seht.
Ich hoffe ihr könnt mir bei meiner Frage auch so weiterhelfen,
da es mehr um ein eingekreister Fehler geht.

Ich habe ein Programm,
dass mehrere Threads nutzt.
Von diesen Threads kann eine Funktion aufgerufen werden die über die 
serielle Schnittstelle Sachen versendet: SendCommand
void SendCommand(uchar adress, uchar command, uchar value) {
  uchar buffer[7];

  buffer[0] = adress | ADRESSBIT;
  buffer[1] = command & ~ADRESSBIT;
  buffer[2] = value & ~ADRESSBIT;
  //printTime();
  //printf("Serial.cpp-SendCommand:\t\tSchreibe Daten");
  //printf(" .");
  select(fd + 1, NULL, &wfds, NULL, NULL);
  //printf(".");
  //printf(".");
  if (FD_ISSET(fd, &wfds)) {
    pthread_mutex_lock(&serial_mutex);
    //printf(".");
    //usleep(500);
    write(fd, buffer, 3);
    //printf(".");
    tcdrain(fd);
    //printf(".");
    pthread_mutex_unlock(&serial_mutex);
    //printf(" fertig\n");

  }
  //else printf(" failed\n");
}
Ich hab diese mit Mutex abgesichert und so weiter. Funktioniert im 
Dauerbetrieb, 24h prima.

Damit das Programm dauernd läuft hab ich in der Main() eine 
Endlosschleife.
Die hat bisher nichts gemacht.

Jetzt fangen die Probleme an:
main() {
/* Initialisierung, Threadstarts */
while(1) {
SendCommand(TEMP_SENS_ADDR1, GET_TEMP, 0x01);
usleep(5000000);
}
return 1;
}
Stecke ich in die Endlosschleife der Main() Funktion eine regelmäßigen
Aufruf auf SendCommand, dann hängt irgendwann, nicht von Anfang an, 
tcdrain() in einer Endlosschleife und damit alles was auf Sendcommand 
beruht. Der Rest läuft weiterhin.

Jetzt meine Frage:
Was kann tcdrain in eine Endlosschleife bringen? Wo, und wie kann die
Fehlersuche am besten machen?

 Gruß Daniel

Autor: Damian (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Daniel,

du schreibst nicht, wie fit du mit Threads bist und welche libc das ist.

Man muss für Multithreading ein Präprozessormakro beim compilieren 
setzen und kann nicht jede Libraryfunktion verwenden. Such mal in diesem 
PDF nach "thread".
http://www.gnu.org/software/libc/manual/pdf/libc.pdf

Gibt es Signalhandler? Da wird Locking zum Problem.



gruss
Damian

Autor: Oliver R. (superberti)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,

bist Du Dir sicher, dass Du tcdrain überhaupt benutzen kannst?

..."The fildes argument is an open file descriptor associated with a 
terminal. "

Ist das bei Dir der Fall? So wie ich das sehe, willst Du nur warten, bis 
write() fertig ist. Wenn Du synchron schreibst, dann ist das doch 
sowieso der Fall. Ich habe jedenfalls schon jede Menge serielle 
Kommunikation unter Linux gemacht, aber tcdrain war noch nie dabei...

Gruß, Oliver

Autor: Daniel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
danke euch zwei.
Ich muss zugeben ich bin in threads nicht sehr bewandert, da ich aus der 
Hardware-Ecke komme. Ja es gibt Signalhandler, ich werde mal
mit euren Stichwörtern weitersuchen.

"fildes" ist bei mir ein geöffneter serieller Port.
Tcdrain() weglassen ist aber auch nicht die Lösung, da ja
irgendwas von mir programmiertes ja schon vorher im argen liegt,
es fällt halt hier auf.
Später kann ich es (wenn besser) auch weglassen :)

Danke!

 Daniel

Autor: Daniel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Achso, und ich nutze die Ubuntu/Eclipse/GCC Entwicklungsumgebung von 
atmel für den AVR32, Plattform NGW100.
Ich verlinke statisch um keine Probleme zu bekommen, das Filesystem
liegt auf SD-Karte, hat also genug freien Platz, es wird
aber im Filesystem auch nicht viel geschrieben.


Sry hatte ich ganz vergessen!

Autor: Daniel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ok, ich hab das Problem weiter eingekreist:
es scheint am Signal-Handling zu liegen.

Momentan hab ich zwei Funktionen, die auf SendCommand
zugreifen können:
- einmal ein Thread (Thread1), der über eine Funktion weckeThread
mit pthread_cond geweckt wird (es wird auch über mutex gelock, wie
es immer in Beispielcodes zu finden ist)
- einmal direkt aus der Endlosschleife in der main

Die Funktion weckeThread ist mit sigaction
dem SIGNAL SIG_USR1 zugewießen.

Kann das Probleme geben?
Ich weiß einfach nicht mehr weiter, ich würde das
Problem gerne verstehen, nicht nur irgendwie umprogrammieren.

In Kürze:
- periodisch:
Main()(endlos): wacht auf -> sendCommand()

- nicht-periodisch
SIG_USR1: weckeThread()->thread_condition
Thread1(endlos): wartet auf thread_condition -> sendCommand()

Gruß daniel

Autor: Damian (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Daniel,

ein Thread, der auf einen Mutex wartet, kann von einem Signalhandler 
unterbrochen werden. Wenn du nun den selben Mutex im Signalhandler noch 
einmal lockst, fängt das Ganze an zu hängen, weil der selbe Thread 
praktisch 2 mal auf die Freigabe des Mutex wartet.

Lösung: Alle Signale am Anfang blocken und einen weiteren Thread 
aufmachen, den du dann mit sigwait() warten und die Arbeit des 
Signalhandlers machen lässt. Dort kann dann wieder fleissig auf den 
Mutex zugegriffen werden. Da der Thread ja aktiv mit sigwait() wartet, 
kann er auch nicht von einem Signal unterbrochen werden, was ja 
anscheinend die Ursache für dein Problem ist.

Da Threads auch nicht so mein täglich Brot sind, schau mal dort bim 
Unterpunkt Signalhandler rein:
http://www.linuxjournal.com/article/2121
ist zwar schon ziemlich alt, aber das Meiste trifft immernoch zu.

gruss Damian

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.