Конференция "Сети" » Виснет TidHTTPServer при попытке его остановки. [D7, WinXP]
 
  • DVM © (09.06.08 14:19) [0]
    При переходе на Indy10 стал виснуть сервер при попытке его остановки, если есть подключенные клиенты. Останавливается как обычно: IdHTTPServer.Active := false;

    Сервер отправляет данные клиентам. Данные бесконечны, поэтому обработчик IdHTTPServerCommandGet выглядит примерно так:

    procedure TfrmMain.IdHTTPServerCommandGet(AContext: TIdContext;
     ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo);
    begin
     ....
     while AContext.Connection.Connected do
       begin
         .... тут отсылаем данные ....
         sleep(0);
         ....
       end;
     ...
    end;

    В предыдущей версии Indy все работало. В новой висит на цикле. Если цикл убрать, то не виснет. Виснет даже с пустым циклом.
    Как с этим бороться?
  • Поросенок Винни-Пух © (09.06.08 14:28) [1]
    Что-то типа
    трай
    сессионнс.локлист
    фор нуль до конца ду гасить колиентов
    файнали
    анлоклист
    енд
  • Anatoly Podgoretsky © (09.06.08 14:43) [2]
    > DVM  (09.06.2008 14:19:00)  [0]

    В  коде не видать IdHTTPServer.Active := false;
  • DVM © (09.06.08 14:45) [3]

    > Anatoly Podgoretsky ©   (09.06.08 14:43) [2]

    procedure TfrmMain.btnStopClick(Sender: TObject);
    var
     Lst: TList;
    begin
     IdHTTPServer.StopListening;
     Lst := IdHTTPServer.Contexts.LockList;
     try
       while Lst.Count > 0 do
         TIdContext(Lst.Items[0]).Connection.Disconnect;
     finally
       IdHTTPServer.Contexts.UnlockList;
     end;
     IdHTTPServer.Active := false;
    end;

    Виснет все равно.
  • Anatoly Podgoretsky © (09.06.08 15:09) [4]
    Теперь не видать удаление элементов из Lst или этим Инди занимается.
    Второе, а ты точно дождался окончания операции Disconnect для каждого элемента списка, это может занимать очень много времени.
    Почему бы для отладки не выводить в метку значение Lst.Count? Тогда сраду будет видно.
    Третье, а в позицию IdHTTPServer.Contexts.UnlockList или IdHTTPServer.Active := false; управление попадает, это же ты должен провести отладку, а не мы.
    Ответь на какой строке у тебя зависает?
  • DVM © (09.06.08 15:24) [5]

    > Теперь не видать удаление элементов из Lst или этим Инди
    > занимается.

    Этим должна заниматься инди вообще то. Я немного неправильно написал вверху, наверное, лучше так, наверное, но это дела не меняет:

    for i := 0 to Lst.Count - 1 do
     TIdContext(Lst.Items[i]).Connection.Disconnect;


    > Ответь на какой строке у тебя зависает?

    IdHTTPServer.Active := false;


    > Второе, а ты точно дождался окончания операции Disconnect
    > для каждого элемента списка, это может занимать очень много
    > времени.

    Нет, не дожидаюсь. Но дело в том, что IdHTTPServer.Active := false; сам по идее должен ждать окончания всех соединений, он и ждет. И не дожидается.
  • Anatoly Podgoretsky © (09.06.08 15:44) [6]
    > DVM  (09.06.2008 15:24:05)  [5]

    Неправильно ты написал сейчас, готовься к исключению.

    >> Ответь на какой строке у тебя зависает?

    > IdHTTPServer.Active := false;

    Означает ли, что ты сюда получаешь управление?
  • DVM © (09.06.08 15:53) [7]

    > Неправильно ты написал сейчас, готовься к исключению.

    Лист залочен и не изменится, какие исключения? Я лишь оповещаю потоки, что пора закругляться. Воообще все эти строки TIdContext(Lst.Items[i]).Connection.Disconnect;
    лишние. В предыдущей версии Инди все работало и само прекрасно завершалось одной строкой IdHTTPServer.Active := false;


    > Означает ли, что ты сюда получаешь управление?
    >

    Да. И дальше пошло поехало в дебри инди, в которых я погряз, пытаясь разобраться где там зависает.
  • Поросенок Винни-Пух © (09.06.08 16:06) [8]
    Я лишь оповещаю потоки, что пора закругляться.

    А им с их синхронными методами по барабану оповещения если конечно нет таймаутов
  • DVM © (09.06.08 16:30) [9]

    > А им с их синхронными методами по барабану оповещения если
    > конечно нет таймаутов

    Ну дык в каждом потоке, крутится мой цикл (см выше), который проверяет флаг Connected.

    Я так понял вначале, что выполнение метода  TIdContext(Lst.Items[i]).Connection.Disconnect; аналогично TThread.Terminate в VCL и устанавливает флаг закругления. Оказывается все не так.
  • DVM © (09.06.08 16:41) [10]
    Вобщем, нашел я ошибку свою и решение.

    В цикле было в коде подавление всех исключений без разбору:

    while AContext.Connection.Connected do
    begin
     ....
     try
       AResponseInfo.WriteContent;
     except
     end;
     ...
    end;
     
    что делало невозможным установку флага Connected со стороны потока, т.к. формально ошибок никаких не возникало (просто неоткуда). Странно, что это работало в предыдущей версии Инди. Если сделать выход по исключению, то все нормально работает.

    while AContext.Connection.Connected do
    begin
     ....
     try
       AResponseInfo.WriteContent;
     except
       exit;
     end;
     ...
    end;
  • DVM © (09.06.08 17:12) [11]
    В догонку, может кому пригодится.

    Еще более правильно и надежно подправить так:

    while ((not (AContext.Yarn as TIdYarnOfThread).Thread.Terminated) and (AContext.Connection.Connected)) do

    begin
      ...
    end;
 
Конференция "Сети" » Виснет TidHTTPServer при попытке его остановки. [D7, WinXP]
Есть новые Нет новых   [134432   +19][b:0][p:0]