Seite 1 von 1
QtProcess unter Linux -> Probleme
Verfasst: 23. Februar 2010 16:08
von Seikilos
Ich hab Code, den ich unter Windows mit Unit Tests verifiziert habe.
Unter Linux krieg ich nicht deterministische Fehler.
Der code:
Code: Alles auswählen
QProcess testproc(this);
printf("vor start\n");
testproc.start("/usr/bin/find");
printf("nach start\n");
printf("error string %s, exit code %d \n",testproc.errorString().toStdString().c_str(), testproc.exitCode());
bool started = testproc.waitForStarted();
printf("started flag %d\n",started);
bool finished = testproc.waitForFinished();
testproc.terminate();
testproc.kill();
printf("finished flag %d, \n", finished);
if(!finished || ( finished && testproc.exitStatus()!=QProcess::NormalExit ))
{
printf("exit %d, \n",testproc.exitStatus());
printf("%s\n",testproc.errorString().toStdString().c_str());
throw std::exception();
}
Was versuche ich hier? Eigentlich versuche ich die Existenz von einem Programm zu verifizieren, das geht nicht. Dann hab ich rausgefunden, dass es mit find auch nicht klappt. Meine Ergebnisse sind:
vor start
nach start
error string Unknown error, exit code 0
unknown location(0): fatal error in "test_name": memory access violation at address: 0x00000000: no mapping at fault address
Die letzte Zeile gehört zum Boost Unit Test Framework, aber dennoch ist die Ausgabe bis dahin falsch, es fehlen eine Menge an Ausgaben und ich weiß einfach nicht, was das Problem sein könnte
Verfasst: 23. Februar 2010 19:10
von kater
Klingt interesannt. Werde mich mal damit befassen.
Verfasst: 24. Februar 2010 08:33
von AuE
Hallo,
erstmal:
Wenn du das ganze so nutzt kannst du auch die statische execute Funktion nutzen. Ich würde dir empfehlen auf den Prozess via Signal Slot zu warten und reagieren.
Das terminat; kill(); Naja.....n lies mal die Doku zu Terminate - die Chance sich zu beenden gibst du ihm nicht wirklich

Ich würde eher nen Timer starten (3Sekunden oder so als Singleshot) und dann wenn dein Prozess noch lebt erst das kill senden.
Das mit dem Find würde ich über ein Skript lösen.
BTW: Deinen Fehler kann ich nicht reproduzieren. Qt 4.6 auf nen Debian AMD x 64
Verfasst: 24. Februar 2010 08:40
von Seikilos
Die Kill und Terminates sind nur Testweise nachträglich reingekommen, weil ich nicht mehr weiter weiß.
Das ganze soll ohne signals und slots arbeiten, weil diese Funktion ein blocking call sein muss und das Programm einfrieren soll, bis es soweit ist.
Die Methode soll nur testen, ob eine bestimmte ausführbare Datei existiert. Das tut sie zwar, aber ich krieg diese grmmpf Fehlermeldung. Dann hab ich es mit /usr/bin/find getestet und da auch, das dürfte ja eigentlich wohl nicht passieren. Meine Meinung nach
Verfasst: 24. Februar 2010 09:01
von AuE
Für blockierenden start ist aber start ungeeignet. Exec macht das ganze bokcieren und gibt dir direkt den Exitcode wieder. Allerdings wenn du nur wissen willst ob ein File da ist ==> QFile::exists(path)
Rechte ==> QFileInfo::permissions () // nicht sicher obs genauso heisst
Des weiteren Überdenke doch bitte die Sache mit den blockieren! Ist sicher manchmal einfacher aber wenns dir abraucht/was nicht klappt ist die GUI Tiefkühlkost.
Verfasst: 24. Februar 2010 09:04
von Seikilos
Es gibt keine GUI an dieser Stelle.
Ich muss überprüfen ob ich eine ausführbare Datei ausführen kann, nicht nur ob sie existiert.
Wenn dieser Check erfolgreich war, wird später mit der ausführbaren Datei richrtig unter Volllast gearbeitet.
Aber irgendwo ist bei mir der Wurm drin. Es klappt unter Windows und unter Linux krieg ich widersprüchliche Ergebnisse, von denen dieser access error am meisten stört
Verfasst: 24. Februar 2010 09:07
von AuE
So und jetz nochmal....warum gehst du den Weg über die Konsole?
Ich würde das via den Standard Qt Funktionen machen. Da bist auf der sicheren Seite und musst net 2 verschieden Konsolen bedienen!
bool QFileInfo::isExecutable () const
Returns true if the file is executable; otherwise returns false.
See also isReadable(), isWritable(), and permission().
bool QFileInfo::exists () const
Returns true if the file exists; otherwise returns false.
Note: If the file is a symlink that points to a non existing file, false is returned.
Verfasst: 24. Februar 2010 09:30
von Seikilos
Weil es ein Konsolenprogramm ist.
Es gibt keine GUI, keine expliziten Threads usw.
Mein Programm ist eine Sammlung von Funktionen, es hat interne algorithmen und nach dem diese durch sind, muss integriert ein anderes Programm aufgerufen werden, damit dieses die Daten weiter verarbeitet.
Es kann nicht lösgelöst vom Hauptprogramm sein, also muss ich es mit QProcess starten.
Hier sollen keine Threads benutzt werden, die Konsole soll blockieren, da der Aufruf des Programms mitunter Tage lang arbeitet und sein IO nach std an die Konsole ausgibt.
Man soll nichts in der Zwischenzeit mit der Konsole machen.
Mir hilft isExecutable usw alles nicht, weil diese Methode ein Test ist, ob Anwendung "XY" verfügbar und ausführbar ist.
Im nächsten Schritt wird diese Anwendung konkret aufgerufen und ausgeführt.
Wenn meine Methode nun isExecutable usw macht, dann verlagere ich die Fehlermeldung, mit der ich diesen Post hier begonnen habe nur in eine andere Methode.
Ich hab im Endeffekt zwei Methoden
checkToolX();
runToolX();
und von der Logik her sollte checkToolX nicht mit isExecutable arbeiten, weil es dann ohne Fehler durchläuft, aber runToolX dann auf die Bretter geht, weil es explizit start, waitForStarted usw aufruft und dann ein memory access violation bekommt
Verfasst: 24. Februar 2010 09:38
von AuE
Also die Fehler die du hast mit der Access Violation haben nichts damit zu tun ob etwas da/ausführbar ist. QFileInfo ist Core Funktionalität also keine GUI spezifische Sache.
Verlagern wir uns also auf das Problem das du hast mit dem ausführen eines Programms.
Ich habe deinen sample Code mehrmals bei mir laufen lassen ohne Probleme.
Trotzdem solltest du, wenn du einen blockierenden start möchtest nicht "start()" nehmen sondern "exec()" ==> siehe Doku.
Von wo/wann kommt diese Fehlermeldung? Die Fehlermeldung sagt mir das da ein NULLptr ist. Ich weiß niocht woher der kommt - evtl eine randerscheinung zwecks deines kill() - weiß ich nicht.
Wieso machst du das kill() an der Stelle?
Ach ja: Unkown error heisst nicht das es einen error gab!
Ach ja (V2): Ich habe bei mir mit qDebug zwecks Ausgabe gearbeitet
Verfasst: 24. Februar 2010 10:21
von franzf
Als alternative herangehensweise:
Verwende ein Config-file (z.B. mit QSettings). Dort trägst du den Pfad zu deiner exe ein.
Bei Programmstart wird die Config gelesen. Existiert der Pfad-Eintrag nicht, teile das dem User mit und terminiere. Exisitiert der Eintrag, prüfe mit QFileInfo, ob die Datei existiert und ausführbar ist. Falls ja -> prima, starte. Falls nein -> User informieren und terminieren.
Einen Test via QProcess empfinde ich als unschön. Das kann immer mal schief gehen (siehe deinen aktuellen Fall).
Als kleiner Tip: Find kann verdammt lange brauchen! In deinem Fall gibst du keine Parameter mit, das heißt find sucht alle Dateien! Ich würde es zum Testen mit Parametern versuchen, die ein schnelles Ende garantieren:
Vllt. ist das bei deinem eigentlichen Programm ähnlich...