#1 2016-03-16 14:33:56

DigDiver
Member
Registered: 2013-04-29
Posts: 137

Problem with TSynBackgroundThreadMethodAbstract

I think, that after Check-in [361888727f] the problem with the executing remote request in a background thread (Client.OnIdle := OnIdleCallback) began.

1. For some unknown reason, the program often goes into an infinite loop in the function TSynBackgroundThreadMethodAbstract.RunAndWait

AcquireThread - returns flagFinished

function TSynBackgroundThreadMethodAbstract.RunAndWait(OpaqueParam: pointer): boolean;
..
  repeat
    case AcquireThread of
    flagDestroying: exit;
    flagIdle: break; // we acquired the background thread
    end;
    case OnIdleProcessNotify(start) of // Windows.GetTickCount64 res is 10-16 ms
    0..20:    SleepHiRes(0);
    21..100:  SleepHiRes(1);
    101..900: SleepHiRes(5);
    else      SleepHiRes(50);
    end;
  until false;

 


2. Or in an infinite loop in the procedure TSynBackgroundThreadMethodAbstract.WaitForFinished(start: Int64)

line: while FixedWaitFor(fCallerEvent,100)<>wrSignaled do
        OnIdleProcessNotify(start);


procedure TSynBackgroundThreadMethodAbstract.WaitForFinished(start: Int64);
...
    if Assigned(fOnIdle) then begin
      while FixedWaitFor(fCallerEvent,100)<>wrSignaled do
        OnIdleProcessNotify(start);

Offline

#2 2016-03-16 14:50:21

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

Re: Problem with TSynBackgroundThreadMethodAbstract

Offline

#3 2016-03-17 06:37:04

DigDiver
Member
Registered: 2013-04-29
Posts: 137

Re: Problem with TSynBackgroundThreadMethodAbstract

Thanks, now works fine!

Offline

#4 2016-03-17 08:06:09

DigDiver
Member
Registered: 2013-04-29
Posts: 137

Re: Problem with TSynBackgroundThreadMethodAbstract

The problem comes back with [f539bea2f8] check-in

In my code I often use Client.UpdateFromServer, that sends two requests to the server with a small time interval between the requests.

 if Assigned(js_accounts) then
   begin
    if not dm.SettingsClient.UpdateFromServer([js_accounts], FRefreshed) then
     if dm.SettingsClient.LastErrorCode <> 503 then
      ShowLastClientError(dm.SettingsClient);
    end

And software goes into an infinite loop in the function TSynBackgroundThreadMethodAbstract.RunAndWait.
AcquireThread - returns flagFinished

Offline

#5 2016-03-17 08:24:31

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

Re: Problem with TSynBackgroundThreadMethodAbstract

But if if we write:

  repeat
    case AcquireThread of
    flagDestroying, flagFinished:
      exit;
    flagIdle:
      break; // we acquired the background thread
    end;

then the regression tests do not pass any more...
This is why I reverted the ", flagFinished" addition...

Offline

#6 2016-03-17 08:39:12

DigDiver
Member
Registered: 2013-04-29
Posts: 137

Re: Problem with TSynBackgroundThreadMethodAbstract

But in the real application, it works (flagFinished).
What is the best solution?

Offline

#7 2016-03-17 10:03:59

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

Re: Problem with TSynBackgroundThreadMethodAbstract

I was not able to reproduce the problem.
The regression tests do pass with no issue.

AFAIK AcquireThread should return flagFinished when a process is about to be finished, so it should never block and achieve either flagIdle or flagDestroying.

Does your client use multiple threads?

Offline

#8 2016-03-17 10:24:11

DigDiver
Member
Registered: 2013-04-29
Posts: 137

Re: Problem with TSynBackgroundThreadMethodAbstract

The problem is that when Client executes a request to the slow server, the BackgroundThread is in active state. And when BackgroundThread executes a request (waiting for the server's response), the client can perform one more request to the server. And at this point, the problem occurs.
I found the solution:

 if dm.SettingsClient.OnIdleBackgroundThreadActive then exit;

or better:

 while dm.SettingsClient.OnIdleBackgroundThreadActive do
  begin
   sleep(30);
   Application.ProcessMessages;
  end;

Offline

#9 2016-03-17 12:05:22

hnb
Member
Registered: 2015-06-15
Posts: 290

Re: Problem with TSynBackgroundThreadMethodAbstract

DigDiver wrote:

when BackgroundThread executes a request (waiting for the server's response), the client can perform one more request to the server. And at this point, the problem occurs.

"one more request" is the real problem in my production :\. In "real" environment with many WiFi it occurs useless very often (note this is not related to BackgroundThread )...


best regards,
Maciej Izak

Offline

#10 2016-03-17 13:05:15

DigDiver
Member
Registered: 2013-04-29
Posts: 137

Re: Problem with TSynBackgroundThreadMethodAbstract

hnb wrote:

"one more request" is the real problem in my production :\. In "real" environment with many WiFi it occurs useless very often (note this is not related to BackgroundThread )...

If SettingsClient.OnIdle is not assigned, any request via SettingsClient will block the User Interface, and the user cannot perform any other actions.
But when SettingsClient.OnIdle is assigned, the UI will be active during the execution of the remote request, and the user can perform any other actions which can produce the infinite loop in the BackgroundThread.
Therefore it is necessary to check OnIdleBackgroundThreadActive

Offline

#11 2016-03-17 15:54:22

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

Re: Problem with TSynBackgroundThreadMethodAbstract

But I still don't understand what's happening here: is the client code executed in the main UI thread, or not?

Offline

#12 2016-04-01 08:17:13

DigDiver
Member
Registered: 2013-04-29
Posts: 137

Re: Problem with TSynBackgroundThreadMethodAbstract

Please download the test project. https://www.dropbox.com/s/pmuwgvr3za72z … s.zip?dl=0
Compile it and run.
Then quickly click two or more times on the button "Call Method".
the program goes into an infinite loop in the function TSynBackgroundThreadMethodAbstract.RunAndWait
AcquireThread - returns flagFinished

Offline

Board footer

Powered by FluxBB