Linux kernel segfault at

🐧 Что такое сообщения «segfault» в файле /var/log/messages

В этом руководстве объясняется, как анализировать сообщение segfault в файле messages и выявлять проблему на стороне приложения или операционной системы.

Что такое «segfault»?

Ошибка сегментации (в оригинале segmentation fault часто сокращаемая до segfault) или нарушение доступа – это ошибка, возникшая у оборудования с защитой памяти, чтобы уведомить операционную систему (ОС) о нарушении доступа к памяти.

Ядро Linux отвечает на него, выполняя некоторые корректирующие действия, обычно передавая ошибку в процесс-нарушитель, посылая процессу сигнал типа # 11.

В некоторых случаях процессы могут устанавливать пользовательский обработчик сигналов, что позволяет им восстанавливаться самостоятельно, но в противном случае используется обработчик сигналов по умолчанию в Linux.

Обычно segfault приводит к завершению процесса и генерирует дамп ядра с правильной настройкой ulimit.

Как проверить?

1. Определить segfault

Ядро просто обнаруживает ошибку процесса или программы и (на некоторых архитектурах) выводит информацию в журнал, как показано ниже:

kernel: login[118125]: segfault at 0 ip 00007f4e4d5334a8 sp 00007fffe9177d60 error 15 in pam_unity_uac.so[7f4e4d530000+b000] kernel: crond[16398]: segfault at 14 ip 00007fd612c128f2 sp 00007fff6a689010 error 4 in pam_seos.so[7fd612baf000+f5000] kernel: crond[17719]: segfault at 14 ip 00007fd612c128f2 sp 00007fff6a689010 error 4 in pam_seos.so[7fd612baf000+f5000

2. Что означает подробности этого сообщения?

Значение RIP – это значение регистра указателя команды, а RSP – значение регистра указателя стека.

Значением ошибки является битовая маска битов кода ошибки страницы (из arch/x86/mm/fault.c):

* bit 0 == 0: no page found 1: protection fault * bit 1 == 0: read access 1: write access * bit 2 == 0: kernel-mode access 1: user-mode access * bit 3 == 1: use of reserved bit detected * bit 4 == 1: fault was an instruction fetch

Вот определение бита ошибки:

01111 ^^^^^ ||||+---> bit 0 |||+----> bit 1 ||+-----> bit 2 |+------> bit 3 +-------> bit 4

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

itisgood
☸️ Установка и использование Helm 3 в кластере Kubernetes
🎄 Как показать анимированную елку в терминале Linux

You may also like

🐧 Сравнение команд Printf и Echo на Linux

🐧 Что означает -z на Bash

🐧 Примеры команд size на Linux

🐧 Linux_Logo – вывод ASCII логотипа Linux с.

🐧 Параметры конфигурационного файла Apt /etc/apt/apt.conf

🐧 Разница между выключением, перезагрузкой и остановкой Linux

⌨️ Введение в команду “./configure”: Компиляция исходного кода.

🐧 Что такое /dev/zero на Linux?

Каковы лучшие дистрибутивы Linux в 2022 году

🐧 Работа с переменной PATH на Linux. Это.

Leave a Comment Cancel Reply

• Свежие записи

• Категории

• Теги

• itsecforu.ru

• Страны посетителей

IT is good

В этой статье вы узнаете, как удалить удаленный Git-репозиторий. Процесс прост, но его полезно запомнить, чтобы избежать неожиданностей в будущем. Git – это…

Читайте также:  Failed code 4 astra linux

В 11-й версии своей операционной системы Microsoft серьезно переработала интерфейс и убрала несколько привычных функций. Нововведения не всем пришлись по душе. Мы дадим…

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

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

Вторичное жильё выгоднее для молодых семей, желающих приобрести свою первую квартиру. Сталкиваясь с ипотечным кредитованием, можно избежать много лишней суеты и проблем, если…

Источник

How to catch segmentation fault in Linux?

I need to catch segmentation fault in third party library cleanup operations. This happens sometimes just before my program exits, and I cannot fix the real reason of this. In Windows programming I could do this with __try — __catch. Is there cross-platform or platform-specific way to do the same? I need this in Linux, gcc.

5 Answers 5

On Linux we can have these as exceptions, too.

Normally, when your program performs a segmentation fault, it is sent a SIGSEGV signal. You can set up your own handler for this signal and mitigate the consequences. Of course you should really be sure that you can recover from the situation. In your case, I think, you should debug your code instead.

Back to the topic. I recently encountered a library (short manual) that transforms such signals to exceptions, so you can write code like this:

Didn’t check it, though. Works on my x86-64 Gentoo box. It has a platform-specific backend (borrowed from gcc’s java implementation), so it can work on many platforms. It just supports x86 and x86-64 out of the box, but you can get backends from libjava, which resides in gcc sources.

Throwing from a signal handler is a very dangerous thing to do. Most compilers assume that only calls can generate exceptions, and set up unwind information accordingly. Languages that transform hardware exceptions into software exceptions, like Java and C#, are aware that anything can throw; this is not the case with C++. With GCC, you at least need -fnon-call-exceptions to ensure that it works–and there is a performance cost to that. There is also a danger that you’ll be throwing from a function without exception support (like a C function) and leak/crash later.

Читайте также:  Linux для tv тюнера

The library is now in github.com/Plaristote/segvcatch, but I couldn’t find the manual or compile it. ./build_gcc_linux_release gives several errors.

Here’s an example of how to do it in C.

#include #include #include #include void segfault_sigaction(int signal, siginfo_t *si, void *arg) < printf("Caught segfault at address %p\n", si->si_addr); exit(0); > int main(void) < int *foo = NULL; struct sigaction sa; memset(&sa, 0, sizeof(struct sigaction)); sigemptyset(&sa.sa_mask); sa.sa_sigaction = segfault_sigaction; sa.sa_flags = SA_SIGINFO; sigaction(SIGSEGV, &sa, NULL); /* Cause a seg fault */ *foo = 1; return 0; >

@TimSeguine: that’s is not true. You just need to make sure you know what you are doing. signal(7) lists all async-signal-safe functions that can be used with relatively little care. In the example above it is also completely safe because nothing else in the program is touching stdout but the printf call in the handler.

@stefanct This is a toy example. Virtually any non-toy program is going to hold the lock on stdout at some point. With this signal handler, the worst that can probably happen is a deadlock on segfault, but that can be bad enough if you currently have no mechanism to kill rogue processes in your use case.

according to 2.4.3 Signal Actions, calling printf from within a signal handler which is called as a result of an illegal indirection, whether the program is multithreaded or not is just plain undefined behavior period.

@TylerDurden First of all, I printf out of exceptions all the time. So you have low standards for the code you write, and you publicly attach your name to that fact. I’m not sure why you’re proud of that, but OK. Secondly your idea that printf uses the heap is totally wrong and you would know that if actually read the source code to a typical printf function. ORLY. You just might want to take your own advice about reading source code before posting something.

For portability, one should probably use std::signal from the standard C++ library, but there is a lot of restriction on what a signal handler can do. Unfortunately, it is not possible to catch a SIGSEGV from within a C++ program without introducing undefined behavior because the specification says:

  1. it is undefined behavior to call any library function from within the handler other than a very narrow subset of the standard library functions ( abort , exit , some atomic functions, reinstall current signal handler, memcpy , memmove , type traits, std::move , std::forward , and some more).
  2. it is undefined behavior if handler use a throw expression.
  3. it is undefined behavior if the handler returns when handling SIGFPE, SIGILL, SIGSEGV
Читайте также:  How to unpack zip linux

This proves that it is impossible to catch SIGSEGV from within a program using strictly standard and portable C++. SIGSEGV is still caught by the operating system and is normally reported to the parent process when a wait family function is called.

You will probably run into the same kind of trouble using POSIX signal because there is a clause that says in 2.4.3 Signal Actions:

The behavior of a process is undefined after it returns normally from a signal-catching function for a SIGBUS, SIGFPE, SIGILL, or SIGSEGV signal that was not generated by kill() , sigqueue() , or raise() .

A word about the longjump s. Assuming we are using POSIX signals, using longjump to simulate stack unwinding won’t help:

Although longjmp() is an async-signal-safe function, if it is invoked from a signal handler which interrupted a non-async-signal-safe function or equivalent (such as the processing equivalent to exit() performed after a return from the initial call to main() ), the behavior of any subsequent call to a non-async-signal-safe function or equivalent is undefined.

This means that the continuation invoked by the call to longjump cannot reliably call usually useful library function such as printf , malloc or exit or return from main without inducing undefined behavior. As such, the continuation can only do a restricted operations and may only exit through some abnormal termination mechanism.

To put things short, catching a SIGSEGV and resuming execution of the program in a portable is probably infeasible without introducing undefined behavior. Even if you are working on a Windows platform for which you have access to Structured exception handling, it is worth mentioning that MSDN suggest to never attempt to handle hardware exceptions: Hardware Exceptions.

At last but not least, whether any SIGSEGV would be raised when dereferencing a null valued pointer (or invalid valued pointer) is not a requirement from the standard. Because indirection through a null valued pointer or any invalid valued pointer is an undefined behaviour, which means the compiler assumes your code will never attempt such a thing at runtime, the compiler is free to make code transformation that would elide such undefined behavior. For example, from cppreference,

Here the true path of the if could be completely elided by the compiler as an optimization; only the else part could be kept. Said otherwise, the compiler infers foo() will never receive a null valued pointer at runtime since it would lead to an undefined behaviour. Invoking it with a null valued pointer, you may observe the value 0 printed to standard output and no crash, you may observe a crash with SIGSEG, in fact you could observe anything since no sensible requirements are imposed on programs that are not free of undefined behaviors.

Источник

Оцените статью
Adblock
detector