Что такое хороший способ сбросить файл ядра Linux изнутри процесса?

У нас есть сервер (написанный на C и С++), который в настоящее время ловит SEGV и выдает некоторую внутреннюю информацию в файл. Я хотел бы создать основной файл и записать его на диск в то время, когда мы поймаем SEGV, поэтому наши представители поддержки и клиенты не должны суетиться с помощью ulimit, а затем ждать, когда авария произойдет снова, чтобы получить ядро файл. Мы использовали функцию прерывания в прошлом, но она подчиняется правилам ulimit и не помогает.

У нас есть некоторый унаследованный код, который читает /proc/pid/map и вручную генерирует основной файл, но он устарел и не выглядит очень портативным (например, я предполагаю, что он не будет работать в наши 64-битные сборки). Каков наилучший способ генерации и сброса основного файла в процессе Linux?

Ответ 1

В Google есть библиотека для генерации исходных кодов внутри выполняемого процесса google-coredumper. Это должно игнорировать ulimit и другие механизмы.

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

Ответ 2

Я увидел сообщение pmbrett и подумал "эй, это круто", но не смог найти эту утилиту где-нибудь в моей системе (Gentoo).

Итак, я немного подтолкнул и обнаружил, что в GDB есть этот параметр.

gdb --pid=4049 --batch -ex gcore

Казалось, что я работаю нормально.

Однако он не очень полезен, потому что он ловушки самой низкой функции, которая использовалась в то время, но она по-прежнему делает хорошую работу за ее пределами (без ограничений памяти, сбрасывается 350M моментальный снимок процесса firefox с ним)

Ответ 3

Попробуйте использовать команду Linux gcore

Использование: gcore [-o имя_файла] pid

Вам нужно будет использовать систему (или exec) и getpid() для создания правильной командной строки, чтобы вызвать ее из вашего процесса

Ответ 4

Некоторые возможные решения ^ W способы решения этой ситуации:

  • Исправить ulimit!!!
  • Примите, что вы не получите файл ядра и запустите его внутри gdb, чтобы создать "thread all apply bt" на SIGSEGV
  • Примите, что вы не получите файл ядра и не получили трассировку стека из приложения. Stack Backtracing Inside Your Program статья довольно старая, но она также должна быть в эти дни.

Ответ 5

Вы также можете изменить ulimit() из вашей программы с помощью setrlimit (2). Как и команда ulimit shell, это может снизить пределы или поднять их так же сильно, как позволяет жесткий предел. При запуске setrlimit() разрешить сброс ядра, и вы в порядке.

Ответ 6

Я предполагаю, что у вас есть обработчик сигналов, который захватывает SEGV, например, и делает что-то вроде печати сообщения и вызывает _exit(). (В противном случае у вас будет файл ядра в первую очередь!) Вы могли бы сделать что-то вроде следующего.

void my_handler(int sig)
{
   ...
   if (wantCore_ && !fork()) {
      setrlimit(...);  // ulimit -Sc unlimited
      sigset(sig, SIG_DFL);  // reset default handler
      raise(sig);  // doesn't return, generates a core file
   }
   _exit(1);
}

Ответ 7

( "kill -6" )

Я бы попробовал, если вы все еще ищете что-то

Ответ 8

используйте обратные трассировки backtrace и backtrace_symbols glibc для получения трассировки, просто имейте в виду, что backtrace_symbols использует malloc внутри, а в случае кучного повреждения он может выйти из строя.