УкраїнськаEnglishmRussian
Вход/Новый
В теме нет новых постов

[BugFixed] daq.Siemens race condition


Автор Сообщение
Сообщение создано: 18. 05. 2011 [08:45]
punk
Василий Петров
Создатель темы
Зарегистрирован(а) с: 09.05.2011
Сообщения: 57
Доброго времени суток!

Обнаружил падение связи с Simatic S7-300.
Если вдруг это важно, то:
- CPU 317-2 (317-2AJ10-0AB0)
- CP 343-1 (343-1EX11-0XE0)
Связь по ethernet/ip. Ошибка проявляется стабильно при следующих условиях:
- нужно считывать около 3 десятков слов с периодом ~800ms
- записывать слово (непериодически) в тот-же контроллер (у меня - виджет от wdg_FormEl)
С какой-то попытки (около 1-2х десятков) связь рвется, ошибка -1025.

Добавив в nodave.c отладочную печать обнаружил, что одна из функции daveReadBytes и daveWriteBytes может быть вызвана до завершения другой и наоборот. Проверено на версиях openscada 0.7.0.2 & 0.7.1. В коде openscada не разбирался, с qt/мультипоточностью дела не имел. Поэтому накидал (коряво) патч, который эти функции лочит прямо в nodave. У меня заработало, обрывы пропали.

Если информации по проблеме недостаточно - допишу.
Если нужно смоделировать на demoDB - могу сделать и прислать модификацию.

собственно патч:

32a33,44

> /*#define sWlock hackedWrLock=1;printf(" SET hacked WR lock\n");
> #define rWlock usleep(100000);hackedWrLock=0;printf(" REset hacked WR

lock\n");
>
> #define sRlock hackedRdLock=1;printf(" SET hacked RD lock\n");
> #define rRlock usleep(100000);hackedRdLock=0;printf(" REset hacked RD lock\n");
> */
> #define sWlock hackedWrLock=1;
> #define rWlock usleep(10000);hackedWrLock=0;
>
> #define sRlock hackedRdLock=1;
> #define rRlock usleep(10000);hackedRdLock=0;
>
59a72,73

> int hackedWrLock=0;
> int hackedRdLock=0;
1195a1210,1215

> //printf (" wait clear WR lock\n");
> while (hackedWrLock==1) {printf(".");usleep(10000);}
> //printf (" DONE: *** wait clear WR lock\n");
>
> sRlock
>
1211c1231

< if (res!=daveResOK) return res;
---
> if (res!=daveResOK) {rRlock return res;}
1215c1235

< if (res!=daveResOK) return res;
---
> if (res!=daveResOK) {rRlock return res;}
1220c1240

< if (res!=daveResOK) return res;
---
> if (res!=daveResOK) {rRlock return res;}
1222a1243

> rRlock
1231a1253

> rRlock
1573a1596,1601

>
> //printf (" wait clear RD lock\n");
> while (hackedRdLock==1) {printf(".");usleep(10000);}
> //printf (" DONE: *** wait clear RD lock\n");
>
> sWlock
1581c1609

< if(res!=daveResOK) return res;
---
> if(res!=daveResOK) {rWlock return res;}
1583c1611

< if(res!=daveResOK) return res;
---
> if(res!=daveResOK) {rWlock return res;}
1584a1613

> rWlock

Сообщение создано: 18. 05. 2011 [09:53]
roman
Roman Savochenko
Moderator
Contributor
Developer
Зарегистрирован(а) с: 12.12.2007
Сообщения: 3750
"punk" wrote:

Связь по ethernet/ip. Ошибка проявляется стабильно при следующих условиях:
- нужно считывать около 3 десятков слов с периодом ~800ms
- записывать слово (непериодически) в тот-же контроллер (у меня - виджет от wdg_FormEl)
С какой-то попытки (около 1-2х десятков) связь рвется, ошибка -1025.

Да действительно, такое может происходить при синхронной записи, что я не очень активно тестировал.
Происходит по причине отсутствия ресурса на доступ к nodave API одного подключения.

"punk" wrote:

Добавив в nodave.c отладочную печать обнаружил, что одна из функции daveReadBytes и daveWriteBytes может быть вызвана до завершения другой и наоборот. Проверено на версиях openscada 0.7.0.2 & 0.7.1. В коде openscada не разбирался, с qt/мультипоточностью дела не имел. Поэтому накидал (коряво) патч, который эти функции лочит прямо в nodave. У меня заработало, обрывы пропали.

Большое спасибо за разборки!
Однако в коде OpenSCADA это решается значительно проще и более правильно.
Исправления добавил и выгрузил в репозиторий r1395(Work) и r1396(0.7.0).

Проверяйте!

Learn, learn and learn better than work, work and work.



1670