Question

I have a project for a windows service which starts a thread to do some job, this part has been working for a long time, so not part of the problem. What I am trying to do is when this job starts and ends, it should start another thread (EventMessenger that inherited TThread) to send emails with a notification about the job has started and ended. I know you can not have nested threads, but i think it should ok to start one thread from another, then it will just belong to the main process. I create the thread in suspended mode, but i am uncertain whether it is ok to call assign for objects on the thread object while it is suspended.

EventMessenger := TEventMessenger.Create(true); // true = start suspended
EventMessenger.StatusCode := AStatusCode;
EventMessenger.Receiver.Assign(Receiver);
EventMessenger.MessageOptions.Assign(MessageOptions);
EventMessenger.MessageDetails := AMessage;
EventMessenger.FreeOnTerminate := true;
EventMessenger.Resume;

The Execute for TEventMessenger sends a mail using Indy TIdSmtp, here is a part of the code

try
  self.FMessage.From.Address := ASender;
  self.FMessage.Recipients.EMailAddresses := AReceiver;
  self.FMessage.Subject := ASubject;
  self.FMessage.Body.Text := AMessage;
  try
    self.FSMTP.Connect;
    self.FSMTP.Send(self.FMessage);
  except
    on E:EIdException do
    begin
      CurrentEurekaLogOptions.ExceptionDialogOptions := []; // Don't show dialog box
      StandardEurekaNotify(E, ExceptAddr()); // Save exception to file
    end;
  end;
finally
  if self.FSMTP.Connected then
    self.FSMTP.Disconnect;
end;

The first time i start the thread EventMessenger it works fine and sends an email about the job has started. However when it starts the EventMessenger again to send a mail about the job has stopped, i got a stack overflow in ntdll. I wonder if the assign in suspended mode can mess up the stack or whether there is some problem in indy; read that it could case problem if exceptions where not masked when mixing managed/unmanaged code, not sure whether this has anything to do with it. Note: I'm not using the default Indy in Delphi 2009, as it has several bugs, I'm running with Indy10 code downloaded from their repository in January.

:779e010f ntdll.KiUserExceptionDispatcher + 0xf
:77a2878b ; ntdll.dll
:779e010f ntdll.KiUserExceptionDispatcher + 0xf
:77a2878b ; ntdll.dll
:779e010f ntdll.KiUserExceptionDispatcher + 0xf
:77a2878b ; ntdll.dll

Any one got a idea what the actually problem is that causes the stack overflow or how i can catch the exception? I have wrapped the indy send in try/except, but i guess that only works for main process not threads, so I also added a try/except around the code in the EventMesssenger.Execute which calls HandleException that I have implemented like the following code, however it service crashes with AV without entering the ExceptionHandler.

procedure TEventMessenger.DoHandleException;
begin
  if FException is Exception then
  begin
    CurrentEurekaLogOptions.ExceptionDialogOptions := []; // Don't show dialog box
    StandardEurekaNotify(FException, ExceptAddr()); // Save exception to file
  end;
end;

procedure TEventMessenger.HandleException;
begin
  FException := Exception(ExceptObject);
  try
    if not (FException is EAbort) then
      Synchronize(DoHandleException);
  finally
    FException := nil;
  end;
end;
Was it helpful?

Solution

To answer your question - Assign() will work just fine while the thread is suspended. You are not touching the stack, as Assign() is a method of TPersistent, and Delphi objects exist on the heap, not the stack.

A stack overflow usually means that you encountered a recursive function call that never ended. Run the code in the debugger and look at the call stack when the overflow occurs, that will help you diagnose which function is getting stuck in a recursive loop.

OTHER TIPS

Found my answer here, seems it had to do with hard-coded breakpoint microsoft had forgot to remove. Unhandled Exception in Rad Studio Debugger Thread

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top