#1 2014-01-09 03:53:24

foncci
Member
Registered: 2013-11-15
Posts: 53

CurrentServiceContext returns RunningThread as NIL randomly

Hi,

CurrentServiceContext returns RunningThread as NIL randomly. sicPerThread service called from multiple threads from one client IP or localhost. It is very simple to reproduce:

Server:
  aModel := TSQLModel.Create([], cServiceName);
  aServer := TSQLRestServerFullMemory.Create(aModel, 'users.json', false, false);
  aServer.ServiceRegister(TServiceIntegrador, [TypeInfo(IServiceIntegrador)], sicPerThread). AllowAll; // .AllowAllByName(['User']);
  aHTTPServer := TSQLHttpServer.Create('8888', [aServer],'+',useHttpApiRegisteringURI, 5, secSynShaAes);  // Is it due to 5 threads? I tried with 10 getting the same NIL result. 


function TServiceIntegrador.UpdSQL(aComando, aData: RawJSON): RawJSON;
var
  Ctxt : TServiceRunningContext;
begin
  Ctxt := CurrentServiceContext;

  if Ctxt.RunningThread=nil then TLogMemo.WriteLog('ThreadID=NIL')
  else TLogMemo.WriteLog('ThreadID='+IntToStr(Ctxt.RunningThread.ThreadID));

  Result := '[]';
end;

Client:
  fModel := TSQLModel.Create([], cServiceName);
  fClient := TSQLHttpClient.Create(aServer, aPort, fModel);
  fClient.Compression := [hcSynLZ, hcDeflate, hcSynShaAes];
  if not fClient.ServerTimeStampSynchronize then raise Exception.Create('Remote service not available on server');

  if // (not fClient.SetUser(aUser, aPass))  or
     (not fClient.ServiceRegister([TypeInfo(IServiceIntegrador)], sicPerThread))
    then raise Exception.Create('Remote service not available on server. 1');

  fService := fClient.Service<IServiceIntegrador>;

jRes := MyCli.fService.UpdSQL(jComando, jData); is called from multiple threads in the same machine. This is not a real life project, it is a test I'm doing while I'm learning the framework. 

Result with 5 threads pool:
ThreadID=9528
ThreadID=NIL
ThreadID=11524
ThreadID=9684
ThreadID=2156
ThreadID=9528
ThreadID=NIL
ThreadID=11524
ThreadID=9684
ThreadID=2156
ThreadID=9528
ThreadID=NIL

Result with 32 threads pool:
ThreadID=5144
ThreadID=11828
ThreadID=2616
ThreadID=8304
ThreadID=9136
ThreadID=8516
ThreadID=11884
ThreadID=6512
ThreadID=7032
ThreadID=6336
ThreadID=NIL   ------------------- NIL
ThreadID=5604
ThreadID=7336
ThreadID=12008
ThreadID=11328
ThreadID=8024
ThreadID=12064
ThreadID=10696
ThreadID=10996
ThreadID=10632
ThreadID=10072
ThreadID=10820
ThreadID=9976
ThreadID=8112
ThreadID=4968
ThreadID=11900
ThreadID=2616
ThreadID=8304
ThreadID=9136
ThreadID=8516
ThreadID=11884
ThreadID=6512
ThreadID=7032
ThreadID=6336
ThreadID=NIL  -------------------------- NIL
ThreadID=5604
ThreadID=7336
ThreadID=12008
ThreadID=11328
ThreadID=8024
ThreadID=12064
ThreadID=10696
ThreadID=10996
ThreadID=10632
ThreadID=10072
ThreadID=10820
ThreadID=9976
ThreadID=8112
ThreadID=4968
ThreadID=11900
ThreadID=9140
ThreadID=10912
ThreadID=11624
ThreadID=11852
ThreadID=12272
ThreadID=8784
ThreadID=5144
ThreadID=6512
ThreadID=7032
ThreadID=6336
ThreadID=NIL  --------------------------------- NIL
ThreadID=5604
ThreadID=8024
ThreadID=12064
ThreadID=10696
ThreadID=10996
ThreadID=10632
ThreadID=10072
ThreadID=10820

Thanks in advance,

Al

Last edited by foncci (2014-01-09 03:59:43)

Offline

#2 2014-01-09 09:25:49

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,659
Website

Re: CurrentServiceContext returns RunningThread as NIL randomly

It's strange.

There is already a dedicated regression test for this:

  ITestPerThread = interface(IInvokable)
    ['{202B6C9F-FCCB-488D-A425-5472554FD9B1}']
    function GetThreadIDAtCreation: cardinal;
    function GetCurrentThreadID: cardinal;
  end;

I'll add a specific test about TServiceRunningContext content.

So I do not understand why it happens.
Are you using the latest unstable 1.18 revision - i.e. http://synopse.info/files/mORMotNightlyBuild.zip ?

Offline

#3 2014-01-09 21:11:13

foncci
Member
Registered: 2013-11-15
Posts: 53

Re: CurrentServiceContext returns RunningThread as NIL randomly

Yes, I'm using the last nightly version. Could you reproduce it ?

Offline

#4 2014-01-10 12:27:54

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,659
Website

Re: CurrentServiceContext returns RunningThread as NIL randomly

Yes, I was able to reproduce it.

We made a deep code refactoring of thread process, especially for TSynThreadPool as used by THttpServer: introducing TNotifiedThread and TSynThreadPoolSubThread.
We also fixed a problem in THttpAPIServer, which was not registering its main execution thread: only the cloned threads were notified, so there was one Ctxt.RunningThread=nil in a row, as you noticed.

As a result, it fixes OnHttpThreadStart and OnHttpThreadTerminate to be triggered from every thread, as expected.
And it fixed TSQLRestServer.BeginCurrentThread/EndCurrentThread process to be triggerred as expected (and checking that it is from the thread itself) - a specific set of regression tests have been introduced to ensure HTTP multi-threaded process works as expected.

See http://synopse.info/fossil/info/795fa3801b

Thanks for the feedback, and code to reproduce!
smile

Offline

Board footer

Powered by FluxBB