13

We have a server (written in C and C++) that currently catches a SEGV and dumps some internal info to a file. I would like to generate a core file and write it to disk at the time we catch the SEGV, so our support reps and customers don't have to fuss with ulimit and then wait for the crash to happen again in order to get a core file. We have used the abort function in the past, but it is subject to the ulimit rules and doesn't help.

We have some legacy code that reads /proc/pid/map and manually generates a core file, but it is out of date, and doesn't seem very portable (for example, I'm guessing it would not work in our 64 bit builds). What is the best way to generate and dump a core file in a Linux process?

Jeremy Mullin
  • 4,170
  • 4
  • 36
  • 54
  • i doubt it's possible, when ulimit rules forbid creating coredumps – Johannes Schaub - litb Nov 25 '08 at 20:02
  • 2
    @JohannesSchaub-litb It's very possible actually. You just use the *`setrlimit(2)`* passing into the first argument ('resource') *`RLIMIT_CORE`*. The inverse of the function is *`getrlimit(2)`* and they are both very useful. – Pryftan Oct 22 '19 at 18:26

8 Answers8

9

Google has a library for generating coredumps from inside a running process called google-coredumper. This should ignore ulimit and other mechanisms.

The documentation for the call that generates the core file is here. According to the documentation, it seems that it is feasible to generate a core file in a signal handler, though it is not guaranteed to always work.

Phillip Whelan
  • 1,697
  • 2
  • 17
  • 28
5

I saw pmbrett's post and thought "hey, thats cool" but couldn't find that utility anywhere on my system ( Gentoo ).

So I did a bit of prodding, and discovered GDB has this option in it.

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

Seemed to work fine for me.

Its not however very useful because it traps the very lowest function that was in use at the time, but it still does a good job outside that ( With no memory limitations, Dumped 350M snapshot of a firefox process with it )

Community
  • 1
  • 1
Kent Fredric
  • 56,416
  • 14
  • 107
  • 150
  • 2
    FYI, the "linux" command 'gcore' is actually a RedHat linux command. It's a bourne shell script that invokes gdb and uses gdb's gcore command to generate the core file. – Michael Snyder Oct 28 '09 at 20:41
4

Try using the Linux command gcore

usage: gcore [-o filename] pid

You'll need to use system (or exec) and getpid() to build up the right command line to call it from within your process

user41716
  • 226
  • 1
  • 3
3

Some possible solutions^W ways of dealing with this situation:

  1. Fix the ulimit!!!
  2. Accept that you don't get a core file and run inside gdb, scripted to do a "thread all apply bt" on SIGSEGV
  3. Accept that you don't get a core file and acquired a stack trace from within the application. The Stack Backtracing Inside Your Program article is pretty old but it should be possible these days too.
activout.se
  • 6,058
  • 4
  • 27
  • 37
  • Thanks for the link to backtrace. 1 and 2 we currently do today when helping customers, but I am looking for a more automated way of retrieving the core file. In Windows we call an API that generates a dump file and can automatically retrieve it. I'd like something similar in our Linux version. – Jeremy Mullin Nov 26 '08 at 14:49
2

You can also change the ulimit() from within your program with setrlimit(2). Like the ulimit shell command, this can lower limits, or raise them as hard as the hard limit allows. At startup setrlimit() to allow core dumping, and you're fine.

  • Just make sure to check for errors. And the inverse is *`getrlimit(2)`* should you want to verify it (without running the other and checking for errors etc.). – Pryftan Oct 22 '19 at 18:31
2

I assume you have a signal handler that catches SEGV, for example, and does something like print a message and call _exit(). (Otherwise, you'd have a core file in the first place!) You could do something like the following.

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);
}
  • Better would be to change the limit when you set up the signal handles - and there you should check errors for *`setrlimit(2)`*. Also if it's the same signal as I recall it'll be trapped again (I am uncertain on this but I believe so). But ultimately *`setrlimit(2)`* is the way to go indeed. – Pryftan Oct 22 '19 at 18:30
1

use backtrace and backtrace_symbols glibc calls to get the trace, just keep in mind that backtrace_symbols uses malloc internally and in case of heap corruption it might fail.

Yusuf Khan
  • 409
  • 3
  • 9
  • This is probably a little known feature but the trouble is this doesn't generate a core and it's not what is being asked. This is great if you want to print out a backtrace for example but it's not the same thing either. It certainly is a useful feature though if you don't want to write your own stack logging system - and you also want information at runtime. Anyway have a +1 - almost 9 years later. – Pryftan Oct 22 '19 at 18:33
0

system ("kill -6 ")

I'd give it a try if you are still looking for something

  • The problem with this method is it won't contain the stack etc. as it would with a crash. The only reason the process would die is because it was directly sent a SIGABRT (which is the better way to do it i.e. *`kill -SIGABRT`*). And SIGSEGV is different in that memory out of the address space was accessed. So although it would generate a core (at least if the ulimit allowed it) it's not the same thing. – Pryftan Oct 22 '19 at 18:24