Einzelnen Beitrag anzeigen

beginnerXE1

Registriert seit: 22. Dez 2020
10 Beiträge
 
#1

OLE Access Violation - Race Conditions?

  Alt 30. Sep 2021, 17:26
Hallo liebe Delphi-Praktiker,

knapp ein Jahr nach dem erfolgreichen Kompilieren einiger Plugins eines alten Projekts ( https://www.delphipraxis.net/206450-...violation.html ) und ein paar weiteren .dll-Änderungen, komme ich nun an ein Problem, wo mir vielleicht ein wenig das Verständnis fehlt.

Ein Arbeitsschritt startet mehrere Threads einer Plugin.dll und beim Aufbau/Laden der Settings gleich zu Beginn kommt es anscheinend zu Race Conditions und in der Folge zu einer Access Violation / einem Lesefehler.
Die Settings werden jeweils aus einer .xml-Datei geladen, die für alle Threads dieselbe ist.
Fall 1: Wird nur 1 Thread gestartet, läuft alles problemlos durch.
Fall 2: Implementiere ich einen Mutex und begrenze den Zugang zu der Funktion "BuildSettingsClass", läuft alles ebenso problemlos durch.
Fall 3: Belasse ich das Laden im Original, kommt es zu den Fehlern, siehe weiter unten.

Mein Problem: am Settings-Laden habe ich nichts verändert zum ursprünglichen Code und mit der Original.dll tritt dieses Problem nicht auf. Meine Änderung ist in einer anderen Datei und hat nichts mit dem Laden zu tun. Zu meiner kleinen Code-Änderung kommt das Plugin gar nicht, weil es beim Laden der Settings schon zu Problemen kommt. Ich kann die Threads auf 1 begrenzen, aber diese Notlösung nervt, ebenso wie der Einbau eines Mutex, wenn es nicht unbedingt sein muss.

Ich habe das Problem mit der Plugin.dll sowohl mit der von Delphi 2010 als auch Delphi 10.3 erzeugten eigenen DLL.
Den Fall 3 habe ich insofern eingegrenzt, indem ich nach jeder Zeile einen Counter erhöht und mir im Fehlerfall / am Funktionsende habe ausgeben lassen. Im Bereich "Verarbeitung" wechselt der Fehlerpunkt immer wieder, aber frühstens immer beim LoadFromFile der XML-Datei.

Mein Verdacht ist, dass das Laden derselbe XML-Datei trotz CoInitializeEx und der Verwendung von NewXMLDocument sowie LoadFromFile nicht Thread-safe ausgeführt wird, aber wenn ich mir nach "NewXMLDocument" mittels "Format('%p', [@XMLDoc])" die Adresse ausgeben lasse (zusammen mit meinem Counter), zeigen beide Threads auf unterschiedliche Adressen.

Vereinfachter Code und hoffentlich auf das Notwendigste begrenzt:
Delphi-Quellcode:
class function TSettingsMisc.BuildSettingsClass(const AFileName: TFileName; const ASettings: TSettings): Boolean;
var
  PerformUnInit: Boolean;
  XMLDoc: IXMLDocument;

  PropCount: Integer;
  PropList: PPropList;
  {...}
begin
  Result := False;
  PerformUnInit := Succeeded(CoInitializeEx(nil, COINIT_MULTITHREADED));
  try
    XMLDoc := NewXMLDocument;
    try
      with XMLDoc do
      begin
        NodeIndentStr := #9;
        Options := Options + [doNodeAutoIndent];
        LoadFromFile(AFileName);
        Active := True;
      end;

      // ab hier meiner Meinung nach irrelevant, "Verarbeitung" mit Zugriff auf verschiedene PropList-Pointer.
       // map xml to settings class
        // based on http://stackoverflow.com/questions/10188459/how-to-loop-all-properties-in-a-class
     
        PropCount := GetPropListCount(ASettings.ClassInfo, PropList);
        GetMem(PropList, PropCount * Sizeof(Pointer));
        try
          GetPropList(ASettings.ClassInfo, PropList);
          { ... }
        finally
          FreeMem(PropList);
        end;
     // "Verarbeitung Ende"
    finally
      XMLDoc := nil;
    end;
  finally
    if PerformUnInit then
      CoUninitialize;
  end;
end;
Ich hoffe, ich habe nichts vergessen / zu viel gekürzt.
Falls jemand auf Anhieb eine Idee hat, wäre ich sehr dankbar. Ich habe über den Counter versucht zu debuggen, weil ich mir nicht sicher war, ob ich beim Delphi Debugger nicht auf diese "Race Condition" einwirke, sofern es eine ist.

Vielen Dank!
PS: Falls es das falsche Unterforum ist, entschuldige ich mich dafür.
  Mit Zitat antworten Zitat