Search code examples
multithreadingdelphiwinapiindy

How can I prevent deadlocks in ApplicationRecoveryCallback()?


I have registered my application for ARR. Assume that my application has a IdTCPServer which reads data from the serial port using VSPE and adds it to a ClientDataSet. If the main thread freezes, ARR will call my ApplicationRecoveryCallback(). Can I access the IdTCPServer in the recovery callback function safely? I want it to stop so that I can save my ClientDataSet to the disk before restarting. Can I simply write my function this way?

function RecoveryFunction(pvParameter: Pointer): DWORD; stdcall;
var
  ContinueRecovery: Boolean;
begin
  Result := 0; // happy compiler ;-)
  repeat
    ApplicationRecoveryInProgress(ContinueRecovery);
    if not ContinueRecovery then
      ApplicationRecoveryFinished(False);
  until frmInstrument.CriticalSection.TryEnter;
  frmInstrument.IdTCPServer.Active := False;
  frmInstrument.CDS.SaveToFile(RecoveryFile);
  ApplicationRecoveryFinished(True);
end;

Solution

  • I wouldn't write it like that. This function is called when your program has stopped responding. For all you know, it's stopped responding because something else is already stuck waiting for that same critical section.

    If you want to be able to access your data even when your program is hung, then you need a lock-free way of detecting when you're allowed to read your data. Use a transaction-log model. Atomically update something that indicates how much of your data is valid. When you enter the recovery function, read that value, and save as much as it says is available. Don't bother reading beyond that point because you can't be certain that it's not corrupt and the reason for your program's crash in the first place.