Зависание при потере сетевого соединения

Вопросы программирования и использования среды Lazarus.

Модератор: Модераторы

Зависание при потере сетевого соединения

Сообщение dmadma » 14.10.2013 00:18:03

Здравствуйте!

Попробуйте провести какой эксперимент.
Создайте новое приложение, новая форма.
Установите подключение к какой либо базе данных (например ADOConnection)
База должна находится удаленно, на соседней машине или на хостинге.
В свойствах в design-time устанавливаем connection:=true - всё ок
Ставим на форму кнопку и таймер.
В таймере выставляем 10 секунд и в обработчике пишем команду halt;
Таймер по умолчанию отключен.
По нажатии на кнопку пишем:
включить таймер, далее сделать любой запрос из базы данных и показать результат на форме.
Всё - этого достаточно для эксперимента.

Запускаем программу (соединение уже установлено). Нажимаем на кнопочку. Раз - появляются результаты запроса и через 10 сек - прога вылетает. Всё отлично.

Теперь вторая попытка, но с небольшим но...

Запускам программу. Теперь вытаскиваем штекер из сетевой карты. Нажимаем на кнопочку. И ВСЁ.... ВИСИМ... Где таймер??? Почему не закрывается программа...

Я понимаю, что соединение прервалось и могут быть какие-то там из-за этого заморочки, но почему таймер не срабатывает? Ведь мы его запустили до того, как начали делать запрос? Почему ВСЁ висит... Причем висит не по какому-то таймауту, а бесконечно...

Пробовал с разными базами, пробовал под Win и под Lin - всё одно...
Что делать? Может кто-то подскажет чего я не понимаю?
dmadma
новенький
 
Сообщения: 12
Зарегистрирован: 13.10.2013 13:30:52

Re: Зависание при потере сетевого соединения

Сообщение alexey38 » 14.10.2013 03:40:11

Насчет бесконечности зависания в ADOConnection не знаю.
Но само подвисание происходит в процедуре запроса. А форма, обработчик таймера, обработчик кнопок - это все один поток. Поэтому зависание любой процедуры приведет к зависанию всего потока, т.е. пока программа не завершит выполнение обработчика кнопки никакой таймер не сработает.
alexey38
долгожитель
 
Сообщения: 1627
Зарегистрирован: 27.04.2011 19:42:31

Re: Зависание при потере сетевого соединения

Сообщение SeZuka » 14.10.2013 07:58:33

может передать timeout в параметрах при подключении?
SeZuka
постоялец
 
Сообщения: 209
Зарегистрирован: 05.09.2012 14:58:05

Re: Зависание при потере сетевого соединения

Сообщение alex208210 » 14.10.2013 12:19:08

правильно alexey38 написал, нужно разветсти по разным потокам подключение к базе и работу таймера
alex208210
постоялец
 
Сообщения: 207
Зарегистрирован: 12.05.2010 13:16:51

Re: Зависание при потере сетевого соединения

Сообщение dmadma » 14.10.2013 13:47:27

Выяснил, что ровно через 18 минут срабатывает исключение sql error lost connection...

Почему так долго и где можно изменить это время до 10 секунд.
Я понимаю, что выставляться это должно на клиенте, так как после разрыва сети сервер недоступен...

Помогите разобраться...
dmadma
новенький
 
Сообщения: 12
Зарегистрирован: 13.10.2013 13:30:52

Re: Зависание при потере сетевого соединения

Сообщение vada » 14.10.2013 17:52:25

Не знаю как вы коннекитесь к базе, но через ODBC/JDBC есть параметр который задает timeout.
Аватара пользователя
vada
энтузиаст
 
Сообщения: 691
Зарегистрирован: 14.02.2006 13:43:17

Re: Зависание при потере сетевого соединения

Сообщение dmadma » 14.10.2013 20:03:22

Не знаю как вы коннекитесь к базе, но через ODBC/JDBC есть параметр который задает timeout.


Коннект к базе здесь не причем. Соединение отрабатывает отлично. Если вытащить шнурок и попытаться установить соединение, то вызывается ошибка мгновенно. Но вот если сначала соединиться, а потом вытащить шнурок - после этого запрос из базы вызывает подвисание всей программы на 18 минут и только после этого выскакивает исключение.

Вопрос - где установлены эти 18 минут (а точнее 17 минут и 45 секунд), потому что именно это время висит - проверял несколько раз. Мне достаточно установить его в 3-5 сек и всё.
Различные переменные timeout на сервере менял - ничего не даёт.

Помогите пожалуйста, вторые сутки бьюсь... по всему интернету всё излазил - не могу ничего сделать...
Неужели все так и работают - ведь это неправильно!
dmadma
новенький
 
Сообщения: 12
Зарегистрирован: 13.10.2013 13:30:52

Re: Зависание при потере сетевого соединения

Сообщение vada » 14.10.2013 23:07:56

Коннект к базе здесь не причем

Очень даже причем. Коннект позволяет задать несколько тайм-аутов. Тайм-аут на коннект и на сокет, к примеру.
Различные переменные timeout на сервере менял - ничего не даёт.

Фигней то маяться зачем? Вы из сервера провод выдрали, как он вам выдаст ошибку по тайм-ауту? Через астрал?
С паскалем я с базой данных не работал. Все больше с JAVA. так у JDBC драйверов есть возможность задать свойство socketTimeout Есть и другие вкусности, например, tcpKeepAlive - булево значение для удержания tcp соединения (ну это нахрен не нужно ващето). Поиск по волшебным словам дает много чего.
http://jdbc.postgresql.org/documentatio ... nnect.html
Также можно задать тайм-аут на SQL запрос.
Код: Выделить всё
        Connection conn = DriverManager.getConnection(url, props);
        PreparedStatement st = conn.prepareStatement("INSERT INTO test VALUES('xxx')");
        st.setQueryTimeout(5);
        st.execute();
Аватара пользователя
vada
энтузиаст
 
Сообщения: 691
Зарегистрирован: 14.02.2006 13:43:17

Re: Зависание при потере сетевого соединения

Сообщение B4rr4cuda » 14.10.2013 23:39:10

Когда на форуме по паскалю дают ответ на джаве... Грядет апокалипсис!
Аватара пользователя
B4rr4cuda
энтузиаст
 
Сообщения: 693
Зарегистрирован: 28.12.2007 07:48:35

Re: Зависание при потере сетевого соединения

Сообщение vada » 15.10.2013 00:15:52

Это просто чтоб знал человек куда копать
Аватара пользователя
vada
энтузиаст
 
Сообщения: 691
Зарегистрирован: 14.02.2006 13:43:17

Re: Зависание при потере сетевого соединения

Сообщение GAMER » 15.10.2013 14:58:27

В параметрах подключения к mysql тоже есть временные параметры, по которым считается таймаут.
Аватара пользователя
GAMER
энтузиаст
 
Сообщения: 627
Зарегистрирован: 06.08.2008 13:41:07
Откуда: Ужгород-Днепр, Украина

Re: Зависание при потере сетевого соединения

Сообщение Xaoc » 31.05.2023 19:18:33

Подскажите вы решение нашли проблемы?
Xaoc
незнакомец
 
Сообщения: 2
Зарегистрирован: 31.05.2023 19:16:05

Re: Зависание при потере сетевого соединения

Сообщение Alex2013 » 31.05.2023 22:56:00

Я в подобном случае просто засунул обращение к сети в отдельный поток (TThread). :idea:
(Видимо частичное игнорирование таймаута это багофича "Форточек" от 10-ки и выше )
Зы
Простейший вариант "оболочки " над операцией ввода вывода.
( Я в курсе что поток может подвиснуть но это куда меньшее золо чем прога повисшая "с концами" (в принципе есть способы завершить поток принудительно но обычно зависшая операция ввода вывода все-же когда-то завершается ))

Код: Выделить всё
Type
TLoad_HTML_Thread=Class(TThread)
  private
  protected
    procedure Execute; override;
    procedure Load;
    procedure SLoad;
  public
    constructor Create(CreateSuspended: boolean;
                            URL:String;TOut,RP:Integer;Var RText:String);
  public
    UPDATE:Boolean;
      Err :Boolean;
      END_T :Boolean;
    fRText:^String;
    fURL:String;
    IsInternet:Boolean;
    fTOut,fRP:Integer;

  end;

procedure TLoad_HTML_Thread.Load;
begin
try
Err:=False;
Err:=LoadHTMPageFromURL(fURL,fTOut,fRP,fRText^)<>'OK';
except
Err:=True;
end;
end;
procedure TLoad_HTML_Thread.SLoad;
begin
IsInternet:= IsInternetConnected ;
Err:= not IsInternet;
end;

procedure TLoad_HTML_Thread.Execute;
begin
while (not Terminated) do
If  UPDATE then begin
Synchronize(@SLoad);
if  IsInternet then  Load;
if  not  End_T then
End_T:=True;
UPDATE  :=False;
end;
END_T:=True;
end;

constructor TLoad_HTML_Thread.Create(CreateSuspended: boolean;
                        URL:String;TOut,RP:Integer;Var RText:String);
begin
END_T:=False;
fUrl:=Url;
fRText:=@Rtext;
fTOut:=TOut;
fRP:=rp;
UPDATE  :=False;
inherited Create(CreateSuspended);
end;

Function Thread_LoadHTML(URL:String;
                          var RS:String;
                          OutTime:TDateTime=1.0 ):Boolean;
var
NTT:TLoad_HTML_Thread;
Const
CTime:TDateTime=0;
begin
Result:=False;
NTT:=TLoad_HTML_Thread.Create(True, URL,Global_Attempts, RS);
NTT.Start;CTime:=Now;NTT.UPDATE:=true;

While not NTT.End_T do begin
Result:= (now-CTime)*10e4 < OutTime ;
if not Result then break;
Application.ProcessMessages;
end;

if Result then Result := NTT.End_T and (Not NTT.Err);
NTT.FreeOnTerminate:=true;
NTT.Terminate;
end
Последний раз редактировалось Alex2013 01.06.2023 12:26:15, всего редактировалось 1 раз.
Alex2013
долгожитель
 
Сообщения: 2938
Зарегистрирован: 03.04.2013 11:59:44

Re: Зависание при потере сетевого соединения

Сообщение Xaoc » 01.06.2023 10:22:38

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

Добавлено спустя 1 час 32 минуты 25 секунд:
Походу я нашел ответ, по крайней мере в моем случае. Только объяснить его не могу.
AstraLinux
параметр tcp_retries2 по умолчанию стоит = 15, установил = 1, обрыв происходит практически мгновенно при разрыве соединения.
команда
sudo sysctl -w net.ipv4.tcp_retries2=1
Xaoc
незнакомец
 
Сообщения: 2
Зарегистрирован: 31.05.2023 19:16:05

Re: Зависание при потере сетевого соединения

Сообщение Alex2013 » 01.06.2023 12:43:41

Xaoc писал(а):Но возникает ситуация, если программа сложная и таких параллельных подзапросов достаточно много, то сколько я могу наплодить подвисших потоков.

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

Добавлено спустя 13 минут 3 секунды:
Xaoc писал(а): Неужели нет возможности установить таймер сброса подключения вручную.

Возможно есть, но скорее всего работает это для каждого конкретного типа операций ввода вывода по разному.
...и беда не в том что нельзя установить значение таймаута а в том что иногда повисает "сам таймаут". :idea:
Alex2013
долгожитель
 
Сообщения: 2938
Зарегистрирован: 03.04.2013 11:59:44


Вернуться в Lazarus

Кто сейчас на конференции

Сейчас этот форум просматривают: Google [Bot] и гости: 11

Рейтинг@Mail.ru