![]() |
Модераторы: Snowy, Poseidon, MetalFan |
![]() ![]() ![]() |
|
Vlarim |
|
|||
Новичок Профиль Группа: Участник Сообщений: 16 Регистрация: 21.8.2011 Репутация: нет Всего: нет |
Добрый день.
Помогите решить проблему зависания приложения. Суть приложения: Цикл каждые 3 мин { - ClientSocket поочередно подключается к 5 железякам, опрашивает, парсит данные, заносит в 2 таблицы - idTelnet подключается к одному серверу, делает 8 запросов, парсит, заносит в другие 2 таблицы. - ServerSocket позволяет подключаться клиентам, после зарешения всех опросов (ClientSocket и idTelnet), данные из таблиц передаются подключенным клиентам (2-6 клиентов). } Все это работает стабильно в течении суток+-. Потом окно перестает обновляться, реагировать на закрытие. Process Explorer показывает 6 потоков: - 4 с именем программы - Wait:UserRequest - WS2_32.dll!SockAsyncTread - Wait:UserRequest - kernel32.dll!BaseThreadStartThunk - Wait:WrLpcReceive Если в каждую процедуру и функцию понатыкать логирование начала и конца, то лог заканчивается всегда на работе таймера. Данный таймер каждый раз сбрасывается после опросов и служит для читаемого отображения отсчета 3х минут (т.е. интервал в 180 сек показывает в виде mm:ss в поле Edit). |
|||
|
||||
kami |
|
|||
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1806 Регистрация: 25.8.2007 Где: Санкт-Петербург Репутация: 6 Всего: 72 |
MadExcept + включение отладочной информации в помощь. При зависании создастся баг-репорт, содержащий полную информацию - что, в какой последовательности вызывалось и на какой строчке зависло.
А что с хендлами и private bytes? Добавлено через 2 минуты и 11 секунд В дополнение:
Случайно в ходе этого Application.ProcessMessages не используется? |
|||
|
||||
Vlarim |
|
|||
Новичок Профиль Группа: Участник Сообщений: 16 Регистрация: 21.8.2011 Репутация: нет Всего: нет |
MadExcept + включение отладочной информации - сделал, придется подождать денек.
Application.ProcessMessages не совсем понятно куда добавлять. ClientSocket работает в NonBlocking. Шлю комманду, полученные данные парсю. Раньше не приходилось работать с отладкой, поэтому хендлы не просматривал, завтра как зависнет - гляну. Присоединённый файл ( Кол-во скачиваний: 6 ) ![]() |
|||
|
||||
kami |
|
|||
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1806 Регистрация: 25.8.2007 Где: Санкт-Петербург Репутация: 6 Всего: 72 |
Никуда не надо, наоборот - от этого костыля, если он есть, надо избавляться. Обычно его использование говорит о... о многом ![]()
меню Project => Madexcept settings => Enable Madexcept (или что-нибудь в этом духе, у меня 3.0, а они вроде как уже 4-ю версию выпустили) галочка поставлена? Там же - check for frozen main thread включено? Если да - тогда ждем багрепорт... Это сообщение отредактировал(а) kami - 12.3.2014, 09:30 |
|||
|
||||
Alexeis |
|
|||
![]() Амеба ![]() Профиль Группа: Админ Сообщений: 11743 Регистрация: 12.10.2005 Где: Зеленоград Репутация: 2 Всего: 459 |
Неуместное использование говорит о многом. В случае когда используется функция WSAAsyncSelect для обработки уведомлений асинхронного сокета в главном потоке, то Application.ProcessMessages как раз таки будет уместно бороться с зависаниями типа дедлока (хотя эффективнее использовать MsgWaitForMultipleObjects с таймаутом). Но в данном случае, ИМХО ситуация больше похожа, на то что одна из сторон аварийно закрыла соединение, а вторая продолжает думать, что соединение еще живое, шлет данные в пустоту и ждет ответа. В этом случае нужно проверять результаты функций recv / send логировать в случае неуспеха. -------------------- Vit вечная память. Обсуждение действий администрации форума производятся только в этом форуме гениальность идеи состоит в том, что ее невозможно придумать |
|||
|
||||
Vlarim |
|
|||
Новичок Профиль Группа: Участник Сообщений: 16 Регистрация: 21.8.2011 Репутация: нет Всего: нет |
Bug report появился еще до зависания приложения, но нет кнопочки Save bug report, извратился картинкой в приложении, добавил кнопку, в следующий раз можно будет сохранить.
Application.ProcessMessages - все же используется в функции для работы с телнетом. Ниже пример функции. У меня малость изменено, пока отлаживал подключение к телнет скидывал все данные в Memo, и в этой функции вместо TelnetBuf - тот же Memo.
check for frozen main thread - не стояла, как зависнет запущу заново уже с этой галкой. Это сообщение отредактировал(а) Vlarim - 13.3.2014, 07:38 Присоединённый файл ( Кол-во скачиваний: 9 ) ![]() |
|||
|
||||
Vlarim |
|
|||
Новичок Профиль Группа: Участник Сообщений: 16 Регистрация: 21.8.2011 Репутация: нет Всего: нет |
Как то в этот раз довольно долго проработала.
Зависла. В приложении репорт с "The application seems to be frozen" Пожалуйста подскажите как выяснить причину. Полгода уже, сил уже нет. Присоединённый файл ( Кол-во скачиваний: 9 ) ![]() |
|||
|
||||
kami |
|
|||
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1806 Регистрация: 25.8.2007 Где: Санкт-Петербург Репутация: 6 Всего: 72 |
Это куда senddata? в клиентский сокет или одно из подключений серверного? Это сообщение отредактировал(а) kami - 19.3.2014, 08:10 |
|||
|
||||
Vlarim |
|
|||
Новичок Профиль Группа: Участник Сообщений: 16 Регистрация: 21.8.2011 Репутация: нет Всего: нет |
В этой процедуре происходит пробегание по строкам таблиц и отправка данных подключенным клиентам.
|
|||
|
||||
kami |
|
|||
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1806 Регистрация: 25.8.2007 Где: Санкт-Петербург Репутация: 6 Всего: 72 |
Смущает одно: в контексте главного потока производится попытка отправки данных в сокет, "принадлежащий" другому потоку (наследник TServerClientThread - TServerThread, если я правильно читаю). Я же ничего не путаю - судя по багрепорту, сервер работает в stThreadBlocking?
Имхо, именно на этом и возникает дедлок. Отправляй данные в контексте своего TServerThread и будет щасте. |
|||
|
||||
Vlarim |
|
|||
Новичок Профиль Группа: Участник Сообщений: 16 Регистрация: 21.8.2011 Репутация: нет Всего: нет |
Т.е в контексте TServerThread добавляю что то вроде:
Вопрос - как в главном потоке вызвать эту процедуру? С примерами туговато по этой части. Это сообщение отредактировал(а) Vlarim - 19.3.2014, 12:42 |
|||
|
||||
kami |
|
|||
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1806 Регистрация: 25.8.2007 Где: Санкт-Петербург Репутация: 6 Всего: 72 |
Стоп-стоп. Я мог сделать неверное предположение, т.к. имею перед глазами только багрепорт, а не исходники.
Кто такой TServerThread? От чего он наследуется? Я правильно понял, что
В любом случае - приведенный в TServerThread.SendAllClients код нельзя считать правильным. У каждого соединения - свой поток. Каждое соединение должно отправлять и принимать данные в контексте своего потока. А в этом методе производится попытка отправить данные всем клиентам из одного потока. Так низзя. За сим - умолкаю, так как с stThreadBlocking не работал, не работаю и не буду, а давать вредные советы - не хочу ![]() Это сообщение отредактировал(а) kami - 19.3.2014, 12:57 |
|||
|
||||
Vlarim |
|
|||
Новичок Профиль Группа: Участник Сообщений: 16 Регистрация: 21.8.2011 Репутация: нет Всего: нет |
Да и на этом спасибо.
Правильнее некуда. Понятно, что из своего потока нужно отправлять сообщение только своему клиенту. Но сколько примеров не видел, все отправляют сообщения из главного потока. Буду продолжать поиски рабочих примеров. |
|||
|
||||
kami |
|
|||
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1806 Регистрация: 25.8.2007 Где: Санкт-Петербург Репутация: 6 Всего: 72 |
Пример, правда - в не-блокирующем режиме
Код заточен под работу из-под любого потока. Выложенная реализация, не лишена недостатков (в частности, в виде утечек памяти). Смотреть метод TDataTransferServer.SendOutStreamToSingleConnection, он асинхронно (в нужном потоке) вызывает событие TDataTransferServer.OnWrite. Общий принцип, реализованный в этом примере - у каждого соединения есть свои буферы на прием и на передачу. Попытка отправить данные - это всего-навсего добавление информации в буфер. А потом - вызов реального "отправщика", в контексте потока, владеющего сокетом. |
|||
|
||||
Vlarim |
|
|||
Новичок Профиль Группа: Участник Сообщений: 16 Регистрация: 21.8.2011 Репутация: нет Всего: нет |
Спасибо за пример.
Попробую разобраться. Сразу возник вопросик, каким образом можно отправить записи. Т.е. я отправляю
Скорее всего надо функцию, которая будет приводить записи к String, а на стороне клиента обратно. Это сообщение отредактировал(а) Vlarim - 24.3.2014, 07:24 |
|||
|
||||
![]() ![]() ![]() |
Правила форума "Delphi: Сети" | |
|
Запрещено: 1. Публиковать ссылки на вскрытые компоненты 2. Обсуждать взлом компонентов и делится вскрытыми компонентами
Если Вам помогли и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, Snowy, Poseidon, MetalFan. |
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
0 Пользователей: | |
« Предыдущая тема | Delphi: Сети | Следующая тема » |
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |