LINUX.ORG.RU

Суть библиотеки errno в Linux

 , ,


0

4

Объясните, пожалуйста, суть библиотеки errno (C/C++) и попутно Линуксе.

P.S. Поиск через гугл дает размытые понятия об этой библиотеке.



Последнее исправление: newbieLX (всего исправлений: 1)

Библиотеки? Или обратно писать в штудии. Пока не узнаешь, что такое препроцессор - не возвращайся.

mittorn ★★★★★
()

А как ты ошибки будешь фиксировать?

Смотри, предположим, что системный вызов вернул ошибку. Короче говоря: эта библиотека позволяет ее(ошибку) зафиксировать, записав в глобальную переменную.

Она определена стандартом POSIX и присутствует практически везде.

p0tsient
()
Ответ на: комментарий от userd

А сохранять дядя Валера их будет? Вот и пишется все это в глобальную переменную errno.

И ошибочный вывод состоит из макросов errno. Подробнее — в позиксы и педивикию.

p0tsient
()
Ответ на: комментарий от p0tsient

Смотри, предположим, что системный вызов вернул ошибку. Короче говоря: эта библиотека позволяет ее(ошибку) зафиксировать, записав в глобальную переменную.

Это жуткий атавизм, рождённый во времена, когда о мультипоточности не задумывались. И дело то не в сисколах, а в соглашениях в libc. Ибо ядро то записывает результат в регистр, если результат успешный, то возвращается >= 0, а если неуспешный, то -errno, которую уже libc инвертирует и прописывает уродское (-1).

vodz ★★★★★
()
Ответ на: комментарий от p0tsient

Так а в чем проблема самостоятельно сохранить в локальную переменную то что вернула функция?
Т.е. что то типа

apr_status_t err;
err = apr_pollset_create(...)
вместо
epfd = epoll_create(...)
if(epfd < 0){
  /*work with errno*/
}
?

userd
()
Ответ на: комментарий от userd

Так а в чем проблема самостоятельно сохранить в локальную переменную то что вернула функция

Так а в чем проблема юзать errno? Тем более, что там еще и макросы для определения ошибок идут в комплекте. Чем пилить каждый раз один и тот же код, лучше юзать заголовочный файл из libc.

p0tsient
()
Ответ на: комментарий от userd

Иногда функция возвращает указатель.

Но насколько я помню, теперь чаще делают возвращаемое значение int с статусом, а указатель пишут в передаваемый параметр. Упрощает жизнь в многопотоке.

Dark_SavanT ★★★★★
()
Ответ на: комментарий от Dark_SavanT

Упрощает жизнь в многопотоке

Понятно, т.е. если нужно передать ошибку в другой поток, обойтись глобальной(пусть даже и thread-local) переменной errno не получится.

userd
()
Ответ на: комментарий от vodz

рождённый во времена, когда о мультипоточности не задумывались.

Я тебя расстрою, но errno себя прекрасно ведет в мультипоточном режиме, ибо глобальная переменная отдельная на каждый поток

PPP328 ★★★★★
()
Ответ на: комментарий от userd

Чаще, пока ты прочитал errno, его уже из другого потока затёрли. И хорошо если OK, так ведь ещё и левую ошибку напишут.

Dark_SavanT ★★★★★
()
Ответ на: комментарий от Dark_SavanT

Стоп, но в том же man errno написано

errno is thread-local; setting it in one thread does not affect its value in any other thread

Или дело в ОС где такое поведение не гарантируется?

userd
()
Ответ на: комментарий от PPP328

errno себя прекрасно ведет в мультипоточном режиме, ибо глобальная переменная отдельная на каждый поток

Это не «прекрасно ведет», а продолжение совместимости путём новой подпорки и костылём: #define errno (*__errno_location ())

vodz ★★★★★
()
Ответ на: комментарий от vodz

Это жуткий атавизм, рождённый во времена, когда о мультипоточности не задумывались.

Можно подумать, для однопоточной среды это решение не криво.

anonymous
()
Ответ на: комментарий от anonymous

Можно подумать, для однопоточной среды это решение не криво.

Скорее всего это было дебилизмом в другом смысле - сделать максимально не похожим на ассемблер. :) Ну и перемудрили. В результате проблема с seek() и sbrk() всё равно осталась (не возможно определить, толи -errno, толи валидное значение в самых старших адресах), тормоза на ровном месте добавили: if(syscall_ret_value_register < 0) { errno = -syscall_ret_value_register; return -1; }. Ну а многопоточность уже окончательно продемонстрировало, что с самого начала думали не тем местом.

vodz ★★★★★
()
Ответ на: комментарий от Dark_SavanT

Да ладно тебе! Я еще на race condition не натыкался: сколько бы ни было потоков, все равно в каждом errno правильно себя ведет. Но на всякий случай я макрообертку использую, чтобы не затереть errno между появлением ошибки и сообщением о ней. Обычная локальная переменная в do{…}while(0).

Если наткнусь-таки на race condition, буду другую обертку делать, уже на более высоком уровне. Но на цепепе я перебираться не собираюсь, уж больно уродливый язык.

anonymous
()
Ответ на: комментарий от vodz

if(syscall_ret_value_register < 0) { errno = -syscall_ret_value_register; return -1; }

Это работает не так. За сообщение об ошибке считается только промежуток значений с -4095 по -1.

Deleted
()
Ответ на: комментарий от Dark_SavanT

Теперь thread-safe, но гарантий тому никаких. Ну и компилировать надо с правильными дефайнами.

Тот факт что у каждого потока свой, независимый errno вполне себе гарантия. Реализовано это так: https://gcc.gnu.org/onlinedocs/gcc/Thread-Local.html#Thread-Local. К слову в C11 этот механизм стандартизировали.

Deleted
()
Ответ на: комментарий от Deleted

Это работает не так.

Это работает для 99% именно так, и данная добавка лишь попытка костылём «решить» противоречие в коде возврата у проблемных функций: sbrk/lseek/mmap.

vodz ★★★★★
()
Ответ на: комментарий от Deleted

К слову в C11 этот механизм стандартизировали.

Окей, теперь верю.

Dark_SavanT ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.