Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Зависание IdHTTPProxyServer [WinXP]


kernel ©   (2009-03-09 08:39:00) 

Доброго времени суток, уважаемые!
Использую последнюю версию Инди. При попытке остановить сабжевый сервер программа (VCL) виснет (хотя сам прокси вроде бы останавливается). Попытки остановить его установкой Activeв falseне успешны. Также пробовал отсоединять каждого юзера из LockList - не помогает (работает через раз). Может быть, сам прокси не правильно создаю (хотя вроде ничего сложного тут нет)?
   mtProxy:=TIdHTTPProxyServer.Create;
   with mtProxy do begin
       DefaultPort:=Port;
       Bindings.DefaultPort:=Port;
       DefaultTransferMode:=tmStreaming;
       Active:=true;
   end;

Я что-то пропустил? В чем может быть проблема?
Заранее благодарю каждого ответившего.


kernel   (2009-03-15 20:29:00) [1]


> Вызов Run всегда происходит раньше вызова Execute

Я обрыл все внутри и Execute, и Run, но так и не нашел, где происходит завис...
PS: Сергей М., спасибо за помощь :)


Сергей М.   (2009-03-15 19:52:00) [2]


> После зависания обращения к Run не происходит


Вызов Run всегда происходит раньшевызова Execute


kernel   (2009-03-15 18:37:00) [3]

Все, устал "ремонтировать" проблему. Отключил TerminateAllYarns, все работает отлично. Только треды, наверное, не убиваются...


kernel   (2009-03-15 15:29:00) [4]

Я совсем уже запутался 8[
После зависания обращения к Run не происходит. Т.е. получается IdThread.Execute всегда успешно проходит.
Где копать?


Сергей М.   (2009-03-10 20:24:00) [5]


> Run же срабатывает только когда к серверу приходит запрос
> от клиента?


Нет, Run вызывается циклически (см. код) до тех пор пока тред, обслуживающий установленное соединение, не перейдет в состояние Stopped.
При этом установившие соединение стороны могут сколь угодно долго "молчать", не проявляя никакой активности.


kernel   (2009-03-10 18:18:00) [6]

Но Run же срабатывает только когда к серверу приходит запрос от клиента? После остановки сервера до Run (и вообще до внутренностей потока) дело не доходит. Он лишь скачет по циклу while True do beginв TerminateAllYarns, а Count в этом же цикле застревает на 1, т.е. в цикле условие
if Count = 0 then begin
  Break;
end;

не проходит.
Я пробовал "отрубать" TerminateAllYarns в IdCustomTCPServer, сервер стабильно отключался. Но что-то меня этот метод пугает...


Сергей М.   (2009-03-10 16:50:00) [7]


> где этот Run искать


Ищи там где он объявлен как override


kernel   (2009-03-10 16:33:00) [8]

Что-то не могу я понять, куда ведет Run (т.е. где этот Run искать)? Или от него сразу идет переход на CommandPassThrough?


Сергей М.   (2009-03-10 15:19:00) [9]


>            if Loop then begin
>                while not Stopped do begin
>                  try
>                     Run; // <-- здесь происходит вызов польз.обработчиков событий. в которых ты волен наплевав на всякие проверки "зависнуть" в блокирующем ожидании чего-либо
>                  except


kernel   (2009-03-10 14:42:00) [10]

Так в тредах же и так проверяется флаг Terminated на каждом шагу?!
...
 while not Terminated do begin
       if Stopped then begin
         DoStopped;
         // It is possible that either in the DoStopped or from another thread,
         // the thread is restarted, in which case we dont want to restop it.
         if Stopped then begin // DONE: if terminated?
           if Terminated then begin
             Break;
           end;
           Suspend; // Thread manager will revive us
           if Terminated then begin
             Break;
           end;
         end;
       end;

       Include(FOptions, itoReqCleanup);
       try
         try
           BeforeRun;
           try
             if Loop then begin
               while not Stopped do begin
                 try
                   Run;
                 except
                   on E: Exception do begin
                     if not HandleRunException(E) then begin
                       Terminate;
                       raise;
                     end;
...

Или я что-то не понимаю?


Сергей М.   (2009-03-10 09:03:00) [11]


> виснет на цикле процедуры TerminateAllYarns


Что ж дальше не пошел ?

В теле TerminateAllYarns для каждого треда, созданного сервером, вызывается метод:

procedure TIdSchedulerOfThread.TerminateYarn(AYarn: TIdYarn);
var
 LYarn: TIdYarnOfThread;
begin
 Assert(AYarn<>nil);
 LYarn := TIdYarnOfThread(AYarn);
 if LYarn.Thread = nil then begin
   FreeAndNil(LYarn);
 end
 else if LYarn.Thread.Suspended then begin
   // If suspended, was created but never started
   // ie waiting on connection accept
   FreeAndNil(LYarn.FThread);
 end else
 begin
   // Is already running and will free itself
   LYarn.Thread.Stop; // <-- смотрим реализацию метода Stop
   // Dont free the yarn. The thread frees it (IdThread.pas)
 end;
end;


procedure TIdThread.Stop;
begin
 FLock.Enter; try
   if not Stopped then begin
     case FStopMode of
       smTerminate: Terminate; // <-- все что делает метод Stop - это взводит у объекта-треда флаг Terminated !!!!!!
       smSuspend: {DO not suspend here. Suspend is immediate. See Execute for implementation};
     end;
     Include(FOptions, itoStopped);
   end;
 finally FLock.Leave; end;
end;



Отсюда вывод - треды сервера д.б. реализованы таким образом, чтобы как можно чаще осуществлялся опрос флага Terminated с целью обнаружения "команды закругляться по хозяйству".


kernel   (2009-03-09 21:23:00) [12]

Добрался до IdScheduler: виснет на цикле процедуры TerminateAllYarns. Может быть нужно IdHTTPProxyServer.Scheduler какой-то указать?


Наверх

Титульная страница Поиск, карта сайта Написать письмо