Как правильно вызывать hal_exit()?
-
- Кандидат
- Сообщения: 43
- Зарегистрирован: 29 янв 2022, 10:49
- Репутация: 1
- Контактная информация:
Как правильно вызывать hal_exit()?
Приветствую!
Не могу разобраться как, и где правильно вызывать hal_exit(). Если происходит завершение без вызова hal_exit(), например при Ctrl-Z, Ctrl-C и тд, то при следующем запуске получаю ошибку:
HAL: ERROR: duplicate component name '<имя компонента>'
HAL: ERROR: component -22 not found
Через signal Handler сделать не получается, потому как метод signalHandler - static. Мне из него не добраться до id компонента.
Деструктор, когда ловится signal тоже не запускается.
Видел тут примеры с безусловным переходом, но это совсем табуретка. На первом курсе вроде бы как объясняют, что использование goto совсем неприличный стиль программирования.
На всякий случай напишу зачем мне это надо все. Решил под себя написать компонент для управления частотником по modbus и оформить все это дело по-человечески, в виде класса и тд. Да и на будущее, мало ли какой компонент написать захочется...
Не могу разобраться как, и где правильно вызывать hal_exit(). Если происходит завершение без вызова hal_exit(), например при Ctrl-Z, Ctrl-C и тд, то при следующем запуске получаю ошибку:
HAL: ERROR: duplicate component name '<имя компонента>'
HAL: ERROR: component -22 not found
Через signal Handler сделать не получается, потому как метод signalHandler - static. Мне из него не добраться до id компонента.
Деструктор, когда ловится signal тоже не запускается.
Видел тут примеры с безусловным переходом, но это совсем табуретка. На первом курсе вроде бы как объясняют, что использование goto совсем неприличный стиль программирования.
На всякий случай напишу зачем мне это надо все. Решил под себя написать компонент для управления частотником по modbus и оформить все это дело по-человечески, в виде класса и тд. Да и на будущее, мало ли какой компонент написать захочется...
Последний раз редактировалось perelep 03 авг 2022, 00:13, всего редактировалось 2 раза.
-
- Кандидат
- Сообщения: 43
- Зарегистрирован: 29 янв 2022, 10:49
- Репутация: 1
- Контактная информация:
Re: Как правильно вызывать hal_exit()?
И еще объясняют, что нет ситуаций, когда это необходимо И что используют goto тогда, когда не умеют правильно.
-
- Мастер
- Сообщения: 1707
- Зарегистрирован: 28 авг 2018, 17:13
- Репутация: 285
- Настоящее имя: Алексей
- Контактная информация:
Re: Как правильно вызывать hal_exit()?
goto нельзя использовать потому что это потенциально опасно с точки зрения внесения багов.
если у вас код вмещается на пару-тройку страниц, как в любом нормальном hal компоненте, ничего особо страшного в goto нет.
если у вас код вмещается на пару-тройку страниц, как в любом нормальном hal компоненте, ничего особо страшного в goto нет.
-
- Кандидат
- Сообщения: 43
- Зарегистрирован: 29 янв 2022, 10:49
- Репутация: 1
- Контактная информация:
Re: Как правильно вызывать hal_exit()?
Я понимаю что можно. Но про то и вопрос был, как избежать этого.
-
- Кандидат
- Сообщения: 43
- Зарегистрирован: 29 янв 2022, 10:49
- Репутация: 1
- Контактная информация:
Re: Как правильно вызывать hal_exit()?
Goto рядом со всякими private, try, catch, изоляцией данных и тд совсем не смотрится. Это прям совсем не в духе С++.
-
- Мастер
- Сообщения: 1707
- Зарегистрирован: 28 авг 2018, 17:13
- Репутация: 285
- Настоящее имя: Алексей
- Контактная информация:
Re: Как правильно вызывать hal_exit()?
А где увидели goto то?
https://github.com/LinuxCNC/linuxcnc/bl ... _generic.c
https://github.com/LinuxCNC/linuxcnc/bl ... _generic.c
Код: Выделить всё
void rtapi_app_exit(void){
//everything is hal_malloc-ed which saves a lot of cleanup here
hal_exit(comp_id);
}
-
- Кандидат
- Сообщения: 43
- Зарегистрирован: 29 янв 2022, 10:49
- Репутация: 1
- Контактная информация:
Re: Как правильно вызывать hal_exit()?
Ну, в том же vfdmod, который взял за основу.
-
- Кандидат
- Сообщения: 43
- Зарегистрирован: 29 янв 2022, 10:49
- Репутация: 1
- Контактная информация:
Re: Как правильно вызывать hal_exit()?
Там то что мне нужно, решено с помощью
И
И в вашем примере тоже такая же история (строка 275):
Код: Выделить всё
goto fail;
Код: Выделить всё
fail:
hal_exit(hal_comp_id);
delete [] hal_udata;
fprintf(stderr, "%s: fatal error.\n", qPrintable(exeName));
return -1;
Код: Выделить всё
fail0:
hal_exit(comp_id);
return -1;
-
- Мастер
- Сообщения: 1707
- Зарегистрирован: 28 авг 2018, 17:13
- Репутация: 285
- Настоящее имя: Алексей
- Контактная информация:
Re: Как правильно вызывать hal_exit()?
так этож чтоб код не дублировать.
возьмите да накопипастьте вместо goto : { hal_exit(comp_id); return -1; }
возьмите да накопипастьте вместо goto : { hal_exit(comp_id); return -1; }
-
- Кандидат
- Сообщения: 43
- Зарегистрирован: 29 янв 2022, 10:49
- Репутация: 1
- Контактная информация:
Re: Как правильно вызывать hal_exit()?
Вот кусок кода. Точнее, это уже псевдокод, удалено все лишнее:
Если так сделать (или еще как угодно, лишь бы не через signal), то тут же выходим их цикла, запускается деструктор, вызывается hal_exit(), нет ни каких ошибок при последующем запуске.
Но если создается ситуация, когда доходит дело до signalHandler (завершение по Ctrl-Z, например), то hal_exit() мне уже не вызвать. И больше мне этот код не запустить, получаю ошибку:
Код: Выделить всё
class altivar320{
private:
modbus_t *ctx;
int hal_comp_id;
static void signalHandler(int signum);
public:
altivar320(){
ctx = modbus_new_rtu(<какие-то значения для инициализации>);
modbus_set_slave(ctx, 1);
hal_ready(hal_comp_id);
}
~altivar320(){
try{
hal_exit(this->hal_comp_id);
modbus_free(this->ctx);
printf("%s\n", "Destructor");
}
catch(const std::exception& e){
printf("%s\n", "catch, destructor");
}
}
int main_loop();
};
void altivar320::signalHandler(int signum){
printf("Caught signal %d\n",signum);
//Здесь я не могу вызвать hal_exit(this->hal_comp_id); Потому как нельзя использовать this из-за static
//До деструктора дело тоже не доходит
}
int altivar320::main_loop(){
signal(SIGINT, this->signalHandler);
signal(SIGKILL, this->signalHandler);
signal(SIGTERM, this->signalHandler);
signal(SIGTSTP, this->signalHandler);
try{
while (1){
printf("%s\n", "while");
throw 1;
}
}
catch(int){
printf("%s\n", "сatch, main loop");
}
return 1;
}
int main(){
altivar320 alt320;
alt320.main_loop();
return 1;
}
Но если создается ситуация, когда доходит дело до signalHandler (завершение по Ctrl-Z, например), то hal_exit() мне уже не вызвать. И больше мне этот код не запустить, получаю ошибку:
Код: Выделить всё
HAL: ERROR: duplicate component name '<имя компонента>'
HAL: ERROR: component -22 not found
-
- Мастер
- Сообщения: 1707
- Зарегистрирован: 28 авг 2018, 17:13
- Репутация: 285
- Настоящее имя: Алексей
- Контактная информация:
Re: Как правильно вызывать hal_exit()?
если прям хочется сделать красиво, в signal надо передавать указатель на метод конкретного объекта. сделать это точно можно.
однако вся эта ООП красота тут ни к чему, ибо signal заменяет предыдущий обработчик, а не добавляет новый.
поэтому пишите comp_id в глобальную переменную, как все и делают.
однако вся эта ООП красота тут ни к чему, ибо signal заменяет предыдущий обработчик, а не добавляет новый.
поэтому пишите comp_id в глобальную переменную, как все и делают.
- MX_Master
- Мастер
- Сообщения: 7469
- Зарегистрирован: 27 июн 2015, 19:45
- Репутация: 3089
- Настоящее имя: Михаил
- Откуда: Алматы
- Контактная информация:
Re: Как правильно вызывать hal_exit()?
Пример из моего драйвера - https://github.com/allwincnc/linuxcnc/b ... isc.c#L992
-
- Кандидат
- Сообщения: 43
- Зарегистрирован: 29 янв 2022, 10:49
- Репутация: 1
- Контактная информация:
Re: Как правильно вызывать hal_exit()?
Спасибо! По делу мне ответить пока нечего, нужно время разобраться.
rtapi_app, это точно мой случай? Это ж realtime hal component? У меня по идее user space HAL component... Тот же vfdmod он user space
rtapi_app, это точно мой случай? Это ж realtime hal component? У меня по идее user space HAL component... Тот же vfdmod он user space
-
- Мастер
- Сообщения: 1707
- Зарегистрирован: 28 авг 2018, 17:13
- Репутация: 285
- Настоящее имя: Алексей
- Контактная информация:
Re: Как правильно вызывать hal_exit()?
вообще нет, гоню. по красоте вот как надо.
хранить список созданных объектов
а по сигналу из статического обработчика делать delete каждому по списку.
вот так будет по феншую
-
- Кандидат
- Сообщения: 43
- Зарегистрирован: 29 янв 2022, 10:49
- Репутация: 1
- Контактная информация:
Re: Как правильно вызывать hal_exit()?
Проще уж тогда вот так сделать:
Только это выглядит не шибко хорошо.
Код: Выделить всё
static volatile sig_atomic_t sig_caugh=1;
class altivar320{
private:
modbus_t *ctx;
int hal_comp_id;
static void signalHandler(int signum);
public:
altivar320(){
ctx = modbus_new_rtu(<какие-то значения для инициализации>);
modbus_set_slave(ctx, 1);
hal_ready(hal_comp_id);
}
~altivar320(){
try{
hal_exit(this->hal_comp_id);
modbus_free(this->ctx);
printf("%s\n", "destructor");
}
catch(const std::exception& e){
printf("%s\n", "catch, destructor");
}
}
int main_loop();
};
void altivar320::signalHandler(int signum){
printf("Caught signal %d\n",signum);
sig_caugh=0;
}
int altivar320::main_loop(){
signal(SIGINT, this->signalHandler);
signal(SIGKILL, this->signalHandler);
signal(SIGTERM, this->signalHandler);
signal(SIGTSTP, this->signalHandler);
while (sig_caugh){
printf("%s\n", "while");
}
return 1;
}
int main(){
altivar320 alt320;
alt320.main_loop();
return 1;
}
- MX_Master
- Мастер
- Сообщения: 7469
- Зарегистрирован: 27 июн 2015, 19:45
- Репутация: 3089
- Настоящее имя: Михаил
- Откуда: Алматы
- Контактная информация:
Re: Как правильно вызывать hal_exit()?
Проще С++ не расчехлять
-
- Кандидат
- Сообщения: 43
- Зарегистрирован: 29 янв 2022, 10:49
- Репутация: 1
- Контактная информация:
Re: Как правильно вызывать hal_exit()?
Еще вот такой вариант придумался
Код: Выделить всё
class altivar320{
private:
modbus_t *ctx;
int hal_comp_id;
static void signalHandler(int signum);
public:
altivar320(){
ctx = modbus_new_rtu(<какие-то значения для инициализации>);
modbus_set_slave(ctx, 1);
hal_ready(hal_comp_id);
}
~altivar320(){
try{
hal_exit(this->hal_comp_id);
modbus_free(this->ctx);
printf("%s\n", "destructor");
}
catch(const std::exception& e){
printf("%s\n", "catch/destructor");
}
}
int main_loop();
};
void altivar320::signalHandler(int signum){
throw signum;
}
int altivar320::main_loop(){
signal(SIGINT, this->signalHandler);
signal(SIGKILL, this->signalHandler);
signal(SIGTERM, this->signalHandler);
signal(SIGTSTP, this->signalHandler);
try{
while (1){
printf("%s\n", "while");
}
}
catch(int x){
printf("%s\n", "catch/while");
printf("Caught signal %d\n",x);
}
return 1;
}
int main(){
altivar320 alt320;
alt320.main_loop();
return 1;
}
-
- Мастер
- Сообщения: 1707
- Зарегистрирован: 28 авг 2018, 17:13
- Репутация: 285
- Настоящее имя: Алексей
- Контактная информация:
Re: Как правильно вызывать hal_exit()?
одно могу сказать.
если на такую чушь тратить несколько дней, результат вряд ли будет.
если на такую чушь тратить несколько дней, результат вряд ли будет.