Jump to content

Broken Pipe!


Recommended Posts

подскажите что такое, и как его лечить

(строка 184)2007-06-11 23:06:59 -- Broken pipe!

2007-06-11 23:06:59 -- Broken pipe!

2007-06-11 23:06:59 -- Broken pipe!

.....................................................

.....................................................

2007-06-11 23:07:00 -- Broken pipe!

2007-06-11 23:07:00 -- Broken pipe!

(строка 1673)2007-06-11 23:07:00 -- Broken pipe!

Link to post
Share on other sites
подскажите что такое, и как его лечить

Это попытка записи в закрытый сокет.

Лечится только при написании кода.

Link to post
Share on other sites
  • 5 months later...

короче ситуация такая:

 

захожу в кофигуратор

правлю юзера

сохраняю

обновляю

во время обновления пытаюсь снова открыть юзера

конфигуратор зависает

в логе стг обнаруживается множество broken pipe

 

что интересно, проблемы была как на версии 2.0, так и на 2.403b сейчас.(bsd410)

Link to post
Share on other sites

судя по теме, там устраняется баг с фаерфоксом, а у меня текстовая БД. Боязно накатывать последнюю бетту. Кто нить может точно сказать про эту проблему?

Link to post
Share on other sites
судя по теме, там устраняется баг с фаерфоксом, а у меня текстовая БД. Боязно накатывать последнюю бетту. Кто нить может точно сказать про эту проблему?

Этот баг точно проявлялся при работе с firebird. В остальных случаях он был или очень редкий или совсем не проявлялся. Непосредственно с firebird он никак не связан, а связан с логирование работы сервера. Можете просто закоментировать код функции printfd в файле common.cpp библиотеки common.lib и пересобрать проект (если у вас stg с динамическими библиотеками - пересобрать библиотеку и положить ее вместо старой). Это должно помочь.

Link to post
Share on other sites

Баг одновременных запросов к сокету конфигуратора, в том числе и из одного конфигуратора у меня наблюдается даже на последней бете с аналогичными симптомами.

Link to post
Share on other sites

Ну, в данном случае это просто параллельные коннекты кассиров, по дебагу я слежу за такими вещами, но вообще надо как то распараллелить систему работы конфигураторов, потому что кассирам это иногда сильно мешает.

Link to post
Share on other sites

Стоп-стоп! Конфигуратор работает по TCP и не держит сессию дольше чем необходимо для трансфера данных. Если в этот момент кто-то еще лезет с подключением - он попадает в очередь на listen до следующего accept. Откуда тут могут быть SIGPIPE?

Хм. Посмотрел на плагин конфигуратора. rsconf.cpp: 126

res = listen(listenSocket, 0);

Попробуйте 0 заменить, скажем, на 16.

man listen:

The  backlog  parameter defines the maximum length the queue of pending connections may grow to.  If a connection request arrives with the queue full the client may receive an error with an indication of  ECONNREFUSED  or,  if  the underlying protocol supports retransmission, the request may be ignored so that retries succeed.

Но все равно не понятно откуда там SIGPIPE.

Link to post
Share on other sites

Да, в очередь он устанавливается, но при большом числе пользователей, обновление списка достаточно длительный процесс (~20-30 сек) и конфигуратор на это время подвисает, часто намертво и приходиться его убивать после чего плодятся Broken pipe.

 

И второй вариант при обновлении списка пользователей отредактировать какого-нибудь пользователя, что вызовет похожие косяки в конфигураторе из-за слишком длительного периода ожидания.

 

Думаю правильнее переписать систему на параллельную обработку запросов конфигураторов.

Link to post
Share on other sites

 

int listen (

 

    SOCKET s,

    int backlog

  );

 

 

Parameters

 

s

 

[in] A descriptor identifying a bound, unconnected socket.

 

backlog

 

[in] The maximum length to which the queue of pending connections can GROW. If this value is SOMAXCONN, then the underlying service provider responsible for socket s will set the backlog to a maximum "reasonable" value.

 

 

Думаю что res = listen(listenSocket, SOMAXCONN); или res = listen(listenSocket, 16) должно помочь сегодня ночью перекомпилим - завтра скажу

Link to post
Share on other sites

первое что мы делали

 

пробывали держать открытый сокет и в конфигураторе

запустить обновление.процедура обновления "висит",но при освобождении сокета

корректно продолжает обновлять список.

 

То-есть запросы на сокет стоят в ожидании и выполняются при достижении своей очереди

так как в серверной части используется работа с сокетами в режиме "O_NONBLOCK"

 

для организации многопоточной обработки с сокетами прийдется переделывать очень много кода

 

для каждого соединия создавать свои нити и корректо их обрабатывать - но такая схема сильно

усложнит сам код.

 

посему с эти нужно смириться и принаровиться.

 

 

Теперь стояла задача заставить сервер вываливать сообщение Broken pipe

что мы не делали у нас ничего не получилось.

 

И здесь на помощь к нам пришла Ирина, вот она явно заметила когда конфигуратор помирал.

А помирал он тогда, когда во время обновления списка она пыталась изменить данные пользователя

 

лезем в коды и что мы видим.

 


int TEditUserForm::SendRequest(list<String> & req)
{
NETTRANSACT nt;
nt.SetServer(settings.server);
nt.SetServerPort(settings.serverPort);
nt.SetLogin(admin.GetLogin());
nt.SetPassword(admin.GetPassword());
nt.SetRxCallback(UsersParseReply);

if (nt.Connect() != st_ok)
   {
   admin.LogOut();
   MessageDlg(nt.GetError(), mtError, TMsgDlgButtons() << mbOK, 0);
   return -1;
   }
else
   {
   if (nt.Transact(&req) != st_ok)
       {
       admin.LogOut();
       MessageDlg(AnsiString("Сервер сообщает об ошибке:\n") + AnsiString(nt.GetError()),
           mtError, TMsgDlgButtons() << mbOK, 0);
       return -1;
       }
   }

nt.Disconnect();

return 0;

 

Вызов nt.Disconnect() - происходит в любом случае установили мы соединение с сервером или нет.

 

Но как я сказал раньше в этот момент идет обновление списка,казалось бы что происходит,

а происходит следующее: соединение мы не смогли установить и вызывам сразу nt.Disconnect();

 

смотрим что у нас там

 


int NETTRANSACT::Disconnect()
{
closesocket(outerSocket);
WSACleanup();
return 0;

 

WSACleanup() - функция завершает работу программы с библиотекой гнезд Ws2_32.dll.

 

вот и ответ !!!!

 

 

Есть два метода решения

 

1. Метод очередной затычки:

 


int TEditUserForm::SendRequest(list<String> & req)
{
NETTRANSACT nt;
nt.SetServer(settings.server);
nt.SetServerPort(settings.serverPort);
nt.SetLogin(admin.GetLogin());
nt.SetPassword(admin.GetPassword());
nt.SetRxCallback(UsersParseReply);

if (nt.Connect() != st_ok)
   {
   admin.LogOut();
   MessageDlg(nt.GetError(), mtError, TMsgDlgButtons() << mbOK, 0);
   return -1;
   }
else
   {
   if (nt.Transact(&req) != st_ok)
       {
       admin.LogOut();
       MessageDlg(AnsiString("Сервер сообщает об ошибке:\n") + AnsiString(nt.GetError()),
           mtError, TMsgDlgButtons() << mbOK, 0);
       return -1;
       }
   nt.Disconnect();
   }

return 0;

 

то есть ставим nt.Disconnect(); на свое место. Но такая же фигня может вылезти еще где-то

 

2. Правильный метод:

 

int NETTRANSACT::Disconnect()
{
closesocket(outerSocket);
// Нужно убрать из метода
WSACleanup();
// до сих пор
return 0;

 

 

int NETTRANSACT::Connect()
{
int ret;

// Нужно убрать из конструктора
ret = WSAStartup(MAKEWORD(1, 1), &wsaData);
if (ret)
   {
   strcpy(errorMsg, WSASTARTUP_FAILED);
   return st_conn_fail;
   }

// до сих пор

 

 

И теперь разово вызвать эти обе функции - но к сожалению на си Я не знаю где их вставить-

но то что их нужно выкинуть из класса - это уж точно

 

на делфе они у меня вставлены в секцию инициализации и финализации соответственно

 

вот часть примера из моего кода

 

........

procedure TNetTransact.Reset;
begin
 FStream.Clear;
end;

var
 WSAData: TWSAData;

procedure Startup;
var
 ErrorCode: Integer;
begin
 ErrorCode := WSAStartup($0101, WSAData);
 if ErrorCode <> 0 then
   raise Exception.Create('WSAStartup');
end;

procedure Cleanup;
var
 ErrorCode: Integer;
begin
 ErrorCode := WSACleanup;
 if ErrorCode <> 0 then
   raise Exception.Create('WSACleanup');
end;

initialization
 Startup;

finalization
 Cleanup;
end.

 

прошу разработчиков внести эти важные коррективы .

 

И естественно выложить свежий релиз конфигуратора

спасибо )))

Link to post
Share on other sites

Это проверено? По поводу WSACleanup?

Я так мыслю, что когда соединение ствится в очередь на listen на стороне инициатора происходит блокировка нити до того момента пока не установится соединение. Потом на клиентской стороне соединение успешно выполняется.

Link to post
Share on other sites

WSACleanup() - функция завершает работу программы с библиотекой гнезд Ws2_32.dll.

 

всех гнезд в данном приложении

 

проверь у себя

 

Есть закономерность - жми обновление списка пользователей и пока он обновляется быстренько любому из них добавь некую сумму денег

 

и полезет то о чем писалось

 

потом перенеси nt.disconnect в правильно место и баг исчезнет

Link to post
Share on other sites

Но ведь на клиентской стороне сокеты блокируемые! Он должен заблокироваться на коннекте до тех пор пока на сервере не освободится сокет.

Link to post
Share on other sites

пардон - согласен,

 

сейчас исходников нету под рукой - но в connect-е поссмотри или вызывается WSACleanup и при каких обстоятельствах

 

в любом случаее это из за этого вызова - глянь

Link to post
Share on other sites

Значит так запустил в режиме отладки

 

 

Обновляется список пользователей

 

в это время мы запускаем изменение параметров

 

затык происходит

 

на вызове

 

int NETTRANSACT::RxHeaderAnswer()

 

здесь мы начинаем принимать данные от сервера.

 

но пока мы до этого дошли

 

произошел где-то раньше nt.disconnect

 

который вызвал WSACleanup.

 

 

короче в классе NETTRANS нужно избавляться от WSACleanup

Link to post
Share on other sites

хочу уточнить что затык происходит даже при попытке вызвать пользователя на редактирование именно в момент обновления списка

Link to post
Share on other sites

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

похоже что сначала, на повторном запросе при выполнении предыдущего, просто зависает конфигуратор.

в логах чисто, однако висит всерьёз и надолго.

а вот когда его пытаешся убить, то в логе и вываливается broken pipe.

по крайней мере в данный момент так было, хотя возможно что broken pipe просто вываливаются с задержкой.

 

А как выключить автоматическое обновление после вызова и закрытия окна редактирования пользователя? Оно ведь время занимает и мешает если вносить многим изменения. Всё же кнопка автообновления не зря придумана.

 

ИМНО надо просто конфигуратору с умом работать.

Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...