You are not logged in.
Pages: 1
Hi,
first of all thank you for a great framework.
While troubleshooting memory leaks in my webservices I ran into a problem with releasing memory allocated for OleDBConnections.
I use TInterfacedObject class, in sicPerSession mode.
here is the scenario:
I implement my own OnHttpThreadTerminate and the original OnHttpThreadTerminate is stored in fOnHttpThreadTerminate variable
here is the relevant excerpt:
procedure TJSONServer.MyHttpThreadTerminate(Sender:TThread);
begin
fPropsMSSql.EndCurrentThread;
fOnHttpThreadTerminate(Sender);
end;
...
...
fHTTPServer := TSQLHttpServer.Create(
aPORTNAME,
[fServerDB],
aHostName,
useHttpApiRegisteringURI,
32,
secSSL);
fOnHttpThreadTerminate :=fHTTPServer.HTTPSErver.OnHttpThreadTerminate;
fHTTPServer.HTTPSErver.OnHttpThreadTerminate := MyHttpThreadTerminate;
I wondered why my MyHttpThreadTerminate wasn't called at all.. I have found out that it is caused by clones of THttpApiServer, that still point to the original onTerminated event procedure.
I have modified your code in SynCrtSock.pas like this:
THttpServerGeneric = class(TNotifiedThread)
protected
...
procedure setOnTerminate(pValue: TNotifyThreadEvent);
public
...
property OnHttpThreadTerminate: TNotifyThreadEvent read fOnTerminate write setOnTerminate;
end;
....
...
procedure THttpServerGeneric.setOnTerminate(pValue: TNotifyThreadEvent);
var i : integer;
begin
fOnTerminate := pValue;
if (self is THttpApiServer) and assigned ((self as THttpApiServer).Clones) and
not assigned((self as THttpApiServer).fowner ) then
begin
for i := 0 to (self as THttpApiServer).Clones.count - 1 do
begin
THttpServerGeneric( (self as THttpApiServer).Clones[i]).OnHttpThreadTerminate := pValue;
end;
end;
end;
after this modification the "MyHttpThreadTerminate" is now allways invoked
Eva
Offline
I've fixed THttpApiServer.OnHttpThreadTerminate event setting propagation to its clones.
See http://synopse.info/fossil/info/b87959a094
My implementation is a little bit cleaner, since it uses an overriden method, but is more or less the same.
Thanks for your feedback!
Online
ok, you are right - I could not forsee all ramifications - therefore I used the more cumbersome variant..
I had another two little silly requests:
1) to expand the set (SysCommon.pas)
IsWord: set of byte =
[ord('0')..ord('9'),ord('a')..ord('z'),ord('A')..ord('Z'),ord('{'),ord('}'),ord('-'),ord('_')];
// instead of current set
IsWord: set of byte =
[ord('0')..ord('9'),ord('a')..ord('z'),ord('A')..ord('Z')];
I often use TSynSQLTableDataSet and I need to fast locate the key - mostly of type Guid
2) while searching for a solution to the Onterminate problem, I stumbled on a small potential problem with EnterCriticalSection ( the leaveCriticalSection is not executed if CurrentThreadConnection exists )
function TSQLDBConnectionPropertiesThreadSafe.ThreadSafeConnection: TSQLDBConnection;
var i: integer;
begin
case fThreadingMode of
tmThreadPool: begin
EnterCriticalSection(fConnectionCS);
try
i := CurrentThreadConnectionIndex;
if i>=0 then begin
result := fConnectionPool.List[i];
if result.IsOutdated then
fConnectionPool.Delete(i) else // release outdated connection
exit; // <---------- here
end;
result := NewConnection;
(result as TSQLDBConnectionThreadSafe).fThreadID := GetCurrentThreadId;
fLatestConnectionRetrievedInPool := fConnectionPool.Add(result)
finally
LeaveCriticalSection(fConnectionCS);
end;
end;
tmMainConnection:
result := inherited GetMainConnection;
else
result := nil;
end;
end;
Eva
Offline
The "exit" command always execute the finally section when is inside of the try ... finally.
Esteban
Offline
1) I would not change the default definition of 'word' to include the GUID values.
It does not make much sense...
But you can use your own method for searching.
2) As EMartin stated, there is no problem in the current implementation: the "exit" runs the "finally" part.
Just check with the debugger.
Online
Pages: 1