2010-06-28 9 views
14

Ich habe ein bisschen Code mit einer Race-Bedingung drin ... Ich weiß, dass es eine Race-Bedingung ist, weil es nicht konsequent passiert, und es scheint häufiger auf Dual-Core-Maschinen passieren .Möglichkeiten, einen Race Condition zu finden

Es passiert nie, wenn ich verfolgen. Es besteht jedoch die Möglichkeit, dass es auch zu einem Deadlock kommen könnte. Durch das Analysieren von Stadien der Fertigstellung von Protokollen, wo dies geschieht und nicht auftritt, konnte ich diesen Fehler auf eine einzige Funktion genau lokalisieren. Allerdings weiß ich nicht, wo im Rahmen der Funktion dies geschieht. Es ist nicht auf der obersten Ebene.

Das Hinzufügen von Protokollanweisungen oder Haltepunkten ändert das Timing, wenn es sich um eine Race-Bedingung handelt, und verhindert dies.

Gibt es eine Technik, die ich verwenden kann, abgesehen von einem Race Condition Analyzer, mit dem ich genau feststellen kann, wo das passiert?

Dies ist in Visual Studio 9, mit C++ (der nicht verwalteten Variante).

+0

Letztes Mal habe ich einen schweren Rennen Zustand hatte ich vor Ort wusste, wo es auftritt, . Ich habe es auf die "altmodische Art und Weise" gemacht und dazu gegriffen, Anrufbäume grafisch darzustellen und die Sperrzeiten für jeden Anruf von Hand hervorzuheben. In meinem Fall wurde es in 2 Quelldateien und eine Handvoll Funktionen verbannt, aber es erwies sich als unbezahlbar. –

Antwort

4

Legen Sie in verschiedenen Teilen Ihres Codes schlafen. Etwas, das threadsafe ist, wird threadsafe sein, selbst wenn es (oder asynchroner Code) für gerade Sekunden schläft.

2

Tatsächlich gibt es einige Versuche, Rennbedingungen automatisch zu finden.

Ein weiterer Begriff, den ich in Verbindung mit Race-Condition Erkennung lesen ist RaceFuzzer, aber ich war nicht in der Lage wirklich nützliche Informationen über sie zu finden.

Ich denke, das ist ein relativ junges Forschungsgebiet, also gibt es - soweit ich weiß - hauptsächlich theoretische Arbeiten zu diesem Thema. Versuchen Sie jedoch, eines der oben genannten Schlüsselwörter zu googeln, vielleicht finden Sie einige nützliche Informationen.

3

Der beste Weg, um diese down zu verfolgen, ist die Verwendung von CHESS in Visual Studio. Dies ist kein einfaches Tool und erfordert wahrscheinlich das schrittweise Testen von Unterabschnitten Ihrer App. Viel Glück.

0

Könnte versuchen, den Code zu buchen. Intel bietet auch verschiedene parallele Tools, die Sie ausprobieren könnten.

2

Ich hatte etwas Glück mit der Verwendung von Tracepoints von Visual Studio, um Rennbedingungen zu finden. Natürlich beeinflusst es immer noch das Timing, aber in den Fällen, in denen ich es verwendet habe, war es zumindest nicht genug, um die Rennbedingungen vollständig zu verhindern. Es schien zumindest weniger störend als dedizierte Protokollierung.

Ansonsten versuchen Sie den Code zu veröffentlichen, damit andere darüber schauen können. Einfach den Code im Detail zu studieren, ist keine schlechte Möglichkeit, die Rennbedingungen zu finden.

+0

+1 Für Codeüberprüfungen. Code-Reviews sind immer eine gute Sache !. –

1

Es kann auch eine Ressource sein, die nicht geschützt ist, was nicht konsistentes Verhalten erklären kann (besonders wenn es auf einem einzelnen Kern gut funktioniert und nicht auf Dual Core). In jedem Fall kann die Code-Überprüfung (sowohl für Race-Bedingungen als auch für nicht Thread-sicheren Quellcode) der kürzeste Weg zur Lösung sein.

2

Also, die Vorschlaghammer-Methode für mich war die folgende, die viel Geduld braucht und im besten Fall Sie auf den richtigen Weg bringen kann.Ich habe das verwendet, um herauszufinden, was mit diesem speziellen Problem vor sich ging. Ich habe Tracepoints verwendet, einen zu Beginn der vermuteten High-Level-Funktion und einen am Ende. Verschieben Sie den Tracepoint nach unten. Wenn das Hinzufügen des Ablaufverfolgungspunkts am Anfang der Funktion dazu führt, dass der Fehler nicht mehr auftritt, verschieben Sie den Ablaufverfolgungspunkt nach unten, bis Sie die Bedingung erneut reproduzieren können. Die Idee ist, dass der Trace-Punkt das Timing nicht beeinflusst, wenn Sie ihn nach dem Aufruf platzieren, der schließlich unsicheren Code auslöst, aber wenn Sie ihn vorher platzieren. Beachten Sie auch Ihr Ausgabefenster. Zwischen welchen Nachrichten tritt Ihr Fehler auf? Sie können Trace-Points verwenden, um auch diesen Bereich einzugrenzen.

Sobald Sie Ihren Fehler auf eine überschaubare Code-Region eingegrenzt haben, können Sie Haltepunkte einfügen und sehen, was die anderen Threads an diesem Punkt vorhaben.

1

Sie können Tools wie Intel Inspector verwenden, die bestimmte Arten von Rennbedingungen prüfen können.

5

Es gibt ein Werkzeug in CLang und gcc 4.8+ namens ThreadSanitizer.

Sie kompilieren Sie den Code mit der -fsanitize=thread Flagge

Beispiel:

$ cat simple_race.cc 
#include <pthread.h> 
#include <stdio.h> 

int Global; 

void *Thread1(void *x) { 
    Global++; 
    return NULL; 
} 

void *Thread2(void *x) { 
    Global--; 
    return NULL; 
} 

int main() { 
    pthread_t t[2]; 
    pthread_create(&t[0], NULL, Thread1, NULL); 
    pthread_create(&t[1], NULL, Thread2, NULL); 
    pthread_join(t[0], NULL); 
    pthread_join(t[1], NULL); 
} 

Und die Ausgabe

$ clang++ simple_race.cc -fsanitize=thread -fPIE -pie -g 
$ ./a.out 
================== 
WARNING: ThreadSanitizer: data race (pid=26327) 
    Write of size 4 at 0x7f89554701d0 by thread T1: 
    #0 Thread1(void*) simple_race.cc:8 (exe+0x000000006e66) 

    Previous write of size 4 at 0x7f89554701d0 by thread T2: 
    #0 Thread2(void*) simple_race.cc:13 (exe+0x000000006ed6) 

    Thread T1 (tid=26328, running) created at: 
    #0 pthread_create tsan_interceptors.cc:683 (exe+0x00000001108b) 
    #1 main simple_race.cc:19 (exe+0x000000006f39) 

    Thread T2 (tid=26329, running) created at: 
    #0 pthread_create tsan_interceptors.cc:683 (exe+0x00000001108b) 
    #1 main simple_race.cc:20 (exe+0x000000006f63) 
================== 
ThreadSanitizer: reported 1 warnings