LINUX.ORG.RU

Работа с errno или куда все записывается

 , ,


0

1

Такой вопрос: Запущен один процесс и один поток, вылетает ошибка и поток с процессом просто крашнулись. Куда записывается ошибка errno, и в какой момент (и как) ее можно прочесть, а в какой уже нельзя? Если возможно, объясните с примером кода.

Ответ на: комментарий от i-rinat

Препод квадратно-гнездовой на лоре бушует походу)

anonymous
()

ошибка errno и крэш это напрямую не связанные события. Обычно креш происходит из-за неправильной обработки ошибки.

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

Там была цитата, что меняет.

Там это где?

Для пользователя errno выглядит как thread-local переменная с глобальной областью видимости. Из неё можно читать, в неё можно писать. Зачем лезть в детали реализации? Ты как-то по-другому начал errno использовать?

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

Там это где?

В цитате.

Для пользователя errno выглядит как thread-local

Ещё бы найти в языке поддержку этого «выглядит». Да нифига оно не выглядит, если не копать errno.h, то оно выглядит как глобальная переменная, но «почему-то» тормозящая на однопоточных программах, а если копать, то то станет понятно почему и каким костылём делают это самое «local».

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

Да нифига оно не выглядит

Плохо смотришь.

(*__errno_location()) в glibc давно уже нет, а где и есть - там это ничего не меняет.

«почему-то» тормозящая на однопоточных программах

Тормозящая errno - это в цитаты.

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

И что это меняет?

Попробуй в структуре сделать поле с именем errno:

#include <errno.h>

int main()
{
  struct { int errno; } s = { 0 };
  return s.errno;
}

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

Имена errno, math_errhandling, setjmp, va_copy и va_end зарезервированы. :-)

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

(*__errno_location()) в glibc давно уже нет

а был? glibc полагается на предоставленное операционной системой. если не предоставлено, то расчехляет принесённый с собой костыль volatile int errno

anonymous
()

Прочесть errno можно всегда. Пока не крэшнулся.

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

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

(*__errno_location()) в glibc давно уже нет, а где и есть - там это ничего не меняет.

glibc-2.25 / gcc-7.1.0 (x86_64-linux)

// a.c
#include <errno.h>

int e() { return errno; }

$ gcc -E a.c -pthread | grep -v ^# | indent
extern int *__errno_location (void) __attribute__ ((__nothrow__, __leaf__)) __attribute__ ((__const__));

int e () {
  return (*__errno_location ());
}
sf ★★★
()

Если крашится, то можно попробовать разрешить core и прочитать с помощью gdb оттуда

sudo здесь для ulimit -c и core_pattern которые у меня на Убунте от юзера не работают:

$ cat testcore.c 
#include "stdio.h"
#include "errno.h"
#include <sys/resource.h>
#include "sys/sysctl.h"

int main(void)
{
  struct rlimit core_limits;
  int *pi = NULL;
  char new_core_pat[] = "core-%e-%s-%p-%t";
  int sys_ctl_name[] = {CTL_KERN, KERN_CORE_PATTERN};

  /* Store the errno location */
  const int *errno_ptr = &errno;

  printf("Enable core dump ...\n");
  core_limits.rlim_cur = core_limits.rlim_max = RLIM_INFINITY;
  setrlimit(RLIMIT_CORE, &core_limits);

  /* Set core file name pattern */
  sysctl(sys_ctl_name, sizeof(sys_ctl_name)/sizeof(int),
         NULL , NULL,
         (void *) new_core_pat, sizeof(new_core_pat));

  errno = 42;
  printf("errno is %d located at %p ...\n", errno, errno_ptr);

  printf("Crash now ...\n");
  *pi = 100; 
  return 0;
}
$ gcc -ggdb -Wall -o testcore testcore.c  

$ sudo ./testcore 
Enable core dump ...
errno is 42 located at 0x7fdda112d698 ...
Crash now ...
Segmentation fault

$ ls
core-testcore-11-4893-1496746773  testcore  testcore.c

$ sudo chmod a+rw ./core-testcore-*

$ gdb testcore ./core-testcore-11-4893-1496746773
GNU gdb (Ubuntu 7.11.1-0ubuntu1~16.04) 7.11.1
...
Reading symbols from testcore...done.
[New LWP 4893]
Core was generated by `./testcore'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0  0x00000000004007a4 in main () at testcore.c:29
29	  *pi = 100; 
(gdb) p *errno_ptr 
$1 = 42
(gdb)
alx777 ★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.