Форум: "Основная";
Текущий архив: 2009.09.20;
Скачать: [xml.tar.bz2];
ВнизТихо умирающее приложение Найти похожие ветки
← →
AlexNe (2008-07-05 18:41) [0]Уважаемые эксперты! Похоже я своими стараниями попал
в ситуацию из которой пока не вижу выхода.
Суть проблемы:
Имеется приложение, работающее с различными удаленными серверами через TSocketConnection, c базой данных Interbase, и с сервером реального времени, который крутится на DOS машине - соотв. через синхронный сокет TIdTCPClient.
Для работы с каждым сервером имеется отдельный поток,
причем поток сокета TIdTCPClient имеет наивысший приоритет.
Приложение работает под WinXP, работает без замечаний иногда 9 часов, иногда 3, затем элегантно, без каких либо сообщений схлопывается (а следом закрываются сервера).
Отслеживание возникающих исключений
(посылка сообщений из Application.OnException другой программе) не дало ничего - все чисто до самого схлопывания.
Запустить программу надолго под отладчиком Delphi я не имею возможности.
Безуспешные попытки найти причину доводят меня до отчаяния.
Уже вырубил на всех TSocketConnection свойство SupportCallBacks в False. Во всех Еxecute потоков защитил в
try-except все что только возможно - не помогает!
Может быть кто-нибудь сталкивался с похожей ситуацией при работе с потоками, или подскажет хотябы в какую сторону искать. Буду признателен за любые замечания
← →
Loginov Dmitry © (2008-07-05 18:59) [1]> или подскажет хотябы в какую сторону искать.
Копать следует путем записи в лог всего и вся (все действия приложения, все сообщения об ошибках с указанием ID потока), а потом часами сидеть и анализировать зависимости между записанными в лог строчками.
Загляни также в системный журнал работы ОС. Из него порой удается извлечь толк.
← →
Сергей М. © (2008-07-05 19:20) [2]
> приложение, работающее с различными удаленными серверами .. схлопывается
> следом закрываются сервера
Полный трындец - рухнул кривой самопальный клиент, и в солидарность ему тут же рухнул сервер-бренд)
Или нет ? Или совсем не так дело обстоит ?)
← →
AlexNe (2008-07-05 19:38) [3]Одна из возможных причин схлопывания, как мне думалось, возникновение Exceptions внутри execute потока.
Действительно, когда снабдил потоки механизмом передачи логов - что-то вроде
procedure TMainTread.Execure;
var Hwnd: THandle;
Txt: string;
cds: CopyDataStruct;
begin
..........
try
.....
except
Txt := "Интересующие параметры";
cds.cbData := length (Txt);
cds.lpData := PChar (Txt);
SendMessage (hwnd, wm_CopyData, 0, Integer (@cds));
end;
.........
end;
обнаружил, что в потоке образуется за секунду куча исключений, которые
не выводятся на экран! Ну и через некоторое время операционка очевидно
убивает приложение.
Фишка в том, что эти ошибки я выловил и убрал, а проблема осталась!
Системный журнал щас пойду копать, спасибо за совет.
← →
AlexNe (2008-07-05 19:41) [4]to Сергей М.
не, сервера тоже самопальные :)
они и должны в случае пропадания всех клиентов закрываться.
А трындец действительно полный.
← →
Loginov Dmitry © (2008-07-05 19:41) [5]> except
> Txt := "Интересующие параметры";
> cds.cbData := length (Txt);
> cds.lpData := PChar (Txt);
> SendMessage (hwnd, wm_CopyData, 0, Integer (@cds));
> end;
А оригинальный текст сообщения об ошибке разве не интересует?
← →
AlexNe (2008-07-05 19:56) [6]Нет, ну конечно, там стоит Exception.Message когда оно есть, плюс номер тика, когда случилось. Или я чего-то не понял? В смысле засунуть туда HandleException?
← →
AlexNe (2008-07-05 20:03) [7]Просмотр системного журнала показал наличие серии ошибок Source="Application Error" Category= "None" Event=1000 но с моментами вылетов эти серии слабо кореллируют
← →
Loginov Dmitry © (2008-07-05 20:19) [8]> Или я чего-то не понял?
да фик тебя знает. Я имел ввиду следующее:
try
except
on E: Exception do
WriteToLog(E.Message);
end;
← →
Сергей М. © (2008-07-05 21:03) [9]
> не, сервера тоже самопальные
Не, тады твоим потугам точно трындец)
Бо ты нишиша не знаешь, что . где, когда и при каких обстоятельствах у тебя чего-то там "попадает".
Ты отладчик-то пользуешь, чудо ?)
Или на бубен уповаешь ?)
← →
AlexNe (2008-07-05 21:10) [10]to Loginov Dmitry
прошу прощения, у меня уже из-за этой проблемы фокус сбивается...
Может быть стоит. Только это ничего не даст - в програме после
каждого try except стоят WriteToLog (т.е SendMessage) , и еще
тестировалось с обработчиком Application.OnException, который как раз
записывал в лог E.Message. Так вот, за ночь ни одной записи об исключительных ситуациях и при этом два схлопывания. То есть, когда начинается разрушение, либо SendMessage не работает, либо черт знает вообще что....
← →
AlexNe (2008-07-05 21:12) [11]to Сергей М.
на бубен, на бубен
← →
Сергей М. © (2008-07-05 21:17) [12]Ну тады тряси)
Авось само рассосется)
Небеса, панимаишь ..
← →
Дмитрий Белькевич © (2008-07-05 21:17) [13]Удалённую отладку используй. Гарантированно Excpeption"ы покажет, да еще и потрассировать даст. Очень помогает, бывает. Особенно, когда клиент на другой стороне шарика ;)
← →
AlexNe (2008-07-05 21:21) [14]Собственно проблема возникла после замены асинхронного, но кривого TClientSocket на не кривой, но синхронный TIdTCPClient для работы с сервером под DOS. Соответственно пришлось засунуть TIdTCPClient в отдельный поток, а потом и все остальные обращения к серверам рассовать по потокам. И в общем все стало работать много лучше, но в отместку этот глюк!
← →
Дмитрий Белькевич © (2008-07-05 21:21) [15]Даже мёртвый поток, кстати, после exception"а может OnTerminate вызвать, если его обработать, конечно. А (Sender as TThread).FatalException иногда интересные данные отдаёт.
← →
Дмитрий Белькевич © (2008-07-05 21:23) [16]Можно еще попробовать Indy обновить до актуальных.
← →
Сергей М. © (2008-07-05 21:30) [17]
> кривого TClientSocket на не кривой, но синхронный TIdTCPClient
Эдаких клоунов, зафиксировавших сей факт, - пруд пруди)
← →
AlexNe (2008-07-05 21:38) [18]to Дмитрий Белькевич
Спасибо, попробую. Насколько понял из хелпа это для серверов под виндой. Есть еще Interbase, но он не падал и ничего особенного не ругался. Досовский сервер пишет подробный лог, пойду его копать.
Про OnTerminate и (Sender as TThread).FatalException напиши завтра, т.к. систему забрали а работу и поэкспериментировать до утра не смогу.
← →
Дмитрий Белькевич © (2008-07-05 21:39) [19]Угу, всё в потоках замечательно работает. Сотни потоков.
← →
AlexNe (2008-07-05 21:40) [20]не напиши завтра а напишу завтра, конечно...
← →
Германн © (2008-07-06 02:34) [21]
> AlexNe (05.07.08 21:21) [14]
>
> Собственно проблема возникла после замены асинхронного,
> но кривого TClientSocket на не кривой, но синхронный TIdTCPClient
Есть ещё ICS. Асинхронный и не очень кривой.
← →
AlexNe (2008-07-06 11:15) [22]to Германн
Спасибо. Буду иметь в виду на будущее.
← →
Slym © (2008-07-07 05:15) [23]AlexNe (05.07.08 21:21) [14]
TClientSocket
Самый прямой из простых оберток на WinSock... и не только асинхронный, но синхронный см ClientType:=ctBlocking;
← →
AlexNe (2008-07-08 11:58) [24]to Slym
Cвязь через TClientSocket с сервером реального времени (на машине под DOS) у меня работала устойчиво только при условии установки наивысшего приоритета для всего клиентского Win приложения. Засунуть в специальный поток его проблематично. При этом, если загрузить сильно клиента, например перерисовкой интерфейса, то часть приходящих с сервера пакетов TClientSocket просто терял...
TIdTCPClient в отдельном потоке теряет ничего.
← →
Slym © (2008-07-08 12:18) [25]AlexNe (08.07.08 11:58) [24]
Cвязь через TClientSocket
покажи как делал
AlexNe (08.07.08 11:58) [24]
Засунуть в специальный поток его проблематично
ничего проблемного:unit Unit2;
interface
uses
Classes,Scktcomp,winsock;
type
TSockThread = class(TThread)
private
protected
procedure Execute; override;
end;
implementation
function SockWaitForData(ASocket:TSocket; ATimeout: Longint): Boolean;
var
FDSet: TFDSet;
TimeVal: TTimeVal;
begin
TimeVal.tv_sec := ATimeout div 1000;
TimeVal.tv_usec := (ATimeout mod 1000) * 1000;
FD_ZERO(FDSet);
FD_SET(ASocket, FDSet);
Result := select(0, @FDSet, nil, nil, @TimeVal) > 0;
end;
function SockReadLn(ASocket:TSocket;ATerminator:char;AMaxLineLength:integer;ATimeOut:Long int):string;
var
Buf:array[byte] of char;
SizeBuf:integer;
r,i:integer;
s:string;
begin
SizeBuf:=SizeOf(Buf);
result:="";
while SockWaitForData(ASocket,ATimeOut) do
begin
r:=recv(ASocket, Buf, SizeBuf, MSG_PEEK);
if r=SOCKET_ERROR then RaiseSocketError(WSAGetLastError, "recv");
i:=LCharPos(@Buf,ATerminator,r);
if i<>0 then r:=i;
r:=recv(ASocket, Buf, r, 0);
if r=SOCKET_ERROR then RaiseSocketError(WSAGetLastError, "recv");
SetString(s,Buf,r);
result:=result+s;
if i<>0 then Break;
end;
if length(result)=0 then exit;
i:=length(result)-1;
if (ATerminator=LF) and (result[i]=CR) then Dec(i);
SetLength(result,i);
end;
{ TSockThread }
procedure TSockThread.Execute;
var
Socket:TClientWinSocket;
s:string;
Code:integer;
begin
Socket:=TClientWinSocket.Create(-1);
try
Socket.ClientType:=ctBlocking;
Socket.Open("192.168.14.2","","",3128);
Socket.SendText("CONNECT hostname HTTP/1.0"#13#10);
Socket.SendText(#13#10);
s:=SockReadLn(Socket.SocketHandle);
Fetch(s," ");
Code:=StrToIntDef(Fetch(s," "),200);
if Code<>200 then raise Exception.CreateFmt("Bad HTTP status code: %d %s",[Code,s]);
repeat until
SockReadLn(PeerSocket.SocketHandle) = "";
...
finally
Socket.Free;
end;
end;
end.
← →
Дмитрий Белькевич © (2008-07-08 12:25) [26]Что-то мне кажется, что решение задачи слишком усложнено. Какую проблему решает система?
← →
Slym © (2008-07-08 12:27) [27]Дмитрий Белькевич © (08.07.08 12:25) [26]
Какую проблему решает система?
2. что за DOS сервер, не порали найти/сделать win аналог?
← →
Eraser © (2008-07-08 15:02) [28]> [0] AlexNe (05.07.08 18:41)
> причем поток сокета TIdTCPClient имеет наивысший приоритет.
сетевым потоком не нужно ставить наивысший приоритет, пустая трата процессорного времени.. работа с сетью - довольно медленная операция.
проблема не в инди скорее всего, там tcp клиент/сервер довольно грамотно написаны. Если приложение падает и даже исключение не вылетает, то скорее всего где-то неверная работа с памятью, либо что-то не корректно вызывается и система сразу прихлопывает приложение. Сетевая часть думаю особо не при чем.
← →
AlexNe (2008-07-08 16:36) [29]Извиняюсь за задержку - у меня последний день командировки и рвут на части.
to Slym ©
Возможно, что-то было с TClientSocket в потоке сделано не так, нужно рыть старый исходник. Но сокет с DOS машиной через несколько минут 10Гц обмена вис, причем ситуация решалась только перезагрузкой DOS
to Дмитрий Белькевич ©
Нет, не усложнено. Система решает задачу управления научным оборудованием, которое разбросано в радиусе 50 м и имеет ограничения по длине проводов связи - отсюда наличие множества серверов на разлинух компах.
to Slym ©
>2. что за DOS сервер, не порали найти/сделать win аналог?
Найти нельзя. Сделать - во- первых нужна система жесткого реального времени, тут скорее QNX. Но главное, то кол-во самодельных железок, для которых по мере развития системы писались дрова - все переписть в обночасье никак не получится, а останавливать ради этого систему никто не даст. Так что живем как живем.
to Eraser ©
? - если кто-то приостановит обмен с DOS машиной на 0.5 с., сработает защита, которая останавливает плавное движение конструкции весом 3.5т.
> Если приложение падает и даже исключение не вылетает, то скорее всего > где-то неверная работа с памятью
что-то похожее на конфликт реентерабельности наблюдается по логам, - два раза произошел вылет при входе в Timer.OnTimer (там ничего нет, кроме обновления интерфейсных элементов).
Поставил на тестирование - до вечера, последний шанс отловить барабашку.
← →
Сергей М. © (2008-07-08 17:25) [30]
> синхронный TIdTCPClient для работы с сервером под DOS
Клиенту глубоко фиолетово, под какой ОС работает сервер.
Равно как и наоборот.
И синхронность или асинхронность тут совершенно ни причем.
← →
AlexNe (2008-07-08 19:18) [31]>Сетевая часть думаю особо не при чем.
← →
AlexNe (2008-07-08 19:22) [32]to Eraser ©
Предположение появилось из-за чрезвычайной редкости события - 1-2 раза за сутки, при том что старая версия с теми же серверам, оборудованием и в том же режиме не падает (хотя и теряет иногда важную информацию)
← →
Сергей М. © (2008-07-08 19:26) [33]
> AlexNe (08.07.08 19:18) [31]
Смотря что ты подразумеваешь под "сетевой частью".
Подозреваю, что ты не имеешь ни малейшего представления о модели OSI.
← →
AlexNe (2008-07-08 22:10) [34]Случилось! Дебаггер указал на ошибку в потоке, в котором сидит IdTCPClient. Лог застопорился перед чтением свойства объекта-наследника соотв. потока. Т.е. какая-то аномалия при работе сокета DOS-Windows.
К сожалению проверить и уточнить получится нескоро, командировка кончилась. Поскольку моя работа с системой прерывается, тему считаю временно закрытой. Всем спасибо за потраченное время и ценную информацию.
← →
Дмитрий Белькевич © (2008-07-08 22:37) [35]>Т.е. какая-то аномалия при работе сокета DOS-Windows.
Наиболее вероятная аномалия - доступ к обломкам разрушенного объекта. Объектам после разрушения присваивай nil, может ошибку удастся "проявить". По AV доступа к 00000000.
Еще немного информации. Если нужен хороший реалтайм, разумно выбросить весь дос и вообще все лишние писюки и, по возможности, самодельные железки вместе с дровами. Сделать промежуточный приём на однокристалках, постараться все данные собирать только ими, благо сейчас их разных есть, можно и абсолютный аналог, и дифференциальный, и цифру забирать, и по многим каналам сразу. Объединить их в сеть (есть железки с готовым железячным tcp стёком), и сливать информацию по мере доступности на писюк.
Сделать единый движок для "пропихивания" инфы в компьютер. И несколько разных драйверов для разных входных данных.
Я, конечно, всех особенностей не знаю, но, скорее всего, должно работать без проблем.
← →
SergeyIT © (2008-07-09 00:02) [36]
> Дмитрий Белькевич © (08.07.08 22:37) [35]
> разумно выбросить весь дос и вообще все лишние писюки
Легко говорить. А кто заплатит за такую переделку?
Как говортся - хорошо быть здоровым и богатым.;)
← →
Anatoly Podgoretsky © (2008-07-09 00:31) [37]> Дмитрий Белькевич (08.07.2008 22:37:35) [35]
Не надо nil, лучше $80808080
← →
Дмитрий Белькевич © (2008-07-09 12:24) [38]>Легко говорить. А кто заплатит за такую переделку?
>Как говортся - хорошо быть здоровым и богатым.;)
Лишние писюки - продать, купить однокристалок. Разницу (если останется) - пропить ;)
Вообще, всё равно придётся им что-то менять, просто "закопаются" со временем. Хотя, может быть я и не прав. Все обстоятельства мне неизвестны.
>Не надо nil, лучше $80808080
Почему, кстати? Нашел только, что FastMM в FullDebugMode атоматом забивает память разрушенных объектов и строк этим значением.
Вот, кстати, еще одна идея: поставить FastMM в FullDebugMode.
← →
Anatoly Podgoretsky © (2008-07-09 13:02) [39]> Дмитрий Белькевич (09.07.2008 12:24:38) [38]
Для того что бы отличить не инициализированое, от уничтоженого.
Методика из FastMM
← →
Сергей М. © (2008-07-09 14:14) [40]
> аномалия при работе сокета DOS-Windows
Что это за сокет такой "DOS-Windows" ?
Какое тебе вообще дело до сокета на другом конце соединения ?
Если там что-то не в порядке, сокет на твоем конце соединения возбудит соответствующее исключение, которое ты должен грамотно обработать.
Страницы: 1 2 вся ветка
Форум: "Основная";
Текущий архив: 2009.09.20;
Скачать: [xml.tar.bz2];
Память: 0.57 MB
Время: 0.005 c