(06-14-2021, 06:17 AM)ZGabrovski@gmail.com Wrote: I found where the problem comes from.
I see that under debug mode there is no problem and it working fine.
I check what was the difference and found that when the options "check and assertions" in "Compiler options->Debug" are switched on everything is ok.
Now the daemon works fine.
I have the same problem, in Delphi 10.4, compiling for Linux.
But what you have done is not the cause of the problem, it seems to be a work-around.
What is happening (and this is a day of intense testing here) if that the system loops in "TerminateAllYarns" and does not come out of it.
This is a BUG in the Indy system, and I cannot fix this; can one of the Indy developers please try to fix this problem?
It isd a _permanent_ bug, and occurs simply every time after the HTTP server is started, at least *one* connection is made to it, and then it is closed.
Code:
I added lots of debug syslogs in the Indy code, and I got this at the end:
IdCustomTCPServer.TerminateAllThreads calls TerminateAllYarns
Sep 1 07:37:47 debian11 sartrackserver[33098]: IdScheduler.TerminateAllYarns loop: Count=1
Sep 1 07:37:47 debian11 sartrackserver[33098]: IdSchedulerOfThread.TerminateYarn
Sep 1 07:37:47 debian11 sartrackserver[33098]: IdSchedulerOfThread.TerminateYarn calls LThread.Stop
Sep 1 07:37:48 debian11 sartrackserver[33098]: IdScheduler.TerminateAllYarns DONE
Sep 1 07:37:48 debian11 sartrackserver[33098]: IdScheduler.TerminateAllYarns loop: Count=1
Sep 1 07:37:48 debian11 sartrackserver[33098]: IdSchedulerOfThread.TerminateYarn
Sep 1 07:37:48 debian11 sartrackserver[33098]: IdSchedulerOfThread.TerminateYarn calls LThread.Stop
Sep 1 07:37:48 debian11 sartrackserver[33098]: IdScheduler.TerminateAllYarns DONE
Sep 1 07:37:48 debian11 sartrackserver[33098]: IdScheduler.TerminateAllYarns loop: Count=1
Etc.
And the code looks like this:
Code:
procedure TIdSchedulerOfThread.TerminateYarn(AYarn: TIdYarn);
var
LYarn: TIdYarnOfThread;
LThread: TIdThreadWithTask;
begin
// Bart
syslog(LOG_NOTICE, 'IdSchedulerOfThread.TerminateYarn');
Assert(AYarn<>nil);
LYarn := TIdYarnOfThread(AYarn);
LThread := LYarn.Thread;
if (LThread <> nil) and (not LThread.Suspended) then begin
// Is still running and will free itself
syslog(LOG_NOTICE, 'IdSchedulerOfThread.TerminateYarn calls LThread.Stop');
LThread.Stop;
// Dont free the yarn. The thread frees it (IdThread.pas)
end else
begin
// If suspended, was created but never started
// ie waiting on connection accept
// RLebeau: free the yarn here as well. This allows TIdSchedulerOfThreadPool
// to put the suspended thread, if present, back in the pool.
syslog(LOG_NOTICE, 'IdSchedulerOfThread.TerminateYarn calls IdDisposeAndNil(LYarn)');
IdDisposeAndNil(LYarn);
end;
end;
procedure TIdThread.Stop;
begin
syslog(LOG_NOTICE, 'IdThread.Stop: Try enter lock');
FLock.Enter;
syslog(LOG_NOTICE, 'IdThread.Stop: locked');
try
if not Stopped then
begin
case FStopMode of
smTerminate: begin syslog(LOG_NOTICE, 'IdThread.Stop calls Terminate'); Terminate; end
// smSuspend: ;{DO not suspend here. Suspend is immediate. See Execute for implementation};
else syslog(LOG_NOTICE, 'IdThread.Stop does NOT call Terminate');
end;
Include(FOptions, itoStopped);
end else syslog(LOG_NOTICE, 'IdThread.Stop: is Stopped. Not doing anything');
finally FLock.Leave; end;
end;
procedure TIdThread.Terminate;
begin
//this assert can only raise if terminate is called on an already-destroyed thread
Assert(FLock<>nil);
FLock.Enter;
try
syslog(LOG_NOTICE, 'IdThread.Terminate calls Include');
Include(FOptions, itoStopped);
syslog(LOG_NOTICE, 'IdThread.Terminate calls inherited Terminate');
inherited Terminate;
finally FLock.Leave; end;
end;