[patch] Do not disappoint on "Create a core file of GDB?"

Jan Kratochvil
2010-01-11T16:03:08Z

Hi,

this is a FAQ, GDB asks "Create a core file of GDB?", user types "y" but
a core file is never created.

It is because distros (at least Fedora) commonly have:
ulimit -S -c 0
ulimit -H -c unlimited

and GDB does not raise its soft limit to hard limit.

But common applications also do not raise it so why should GDB? Soft limit is
there to act as default value for the application. GDB is different as it
explicitly asks the user - in such case it should IMO raise the core limit.

Even in the case of "maint set internal-error corefile yes" it had to be set
explicitly by the user as the default is "ask", therefore it should override
the soft core limit.

setrlimit is a POSIX function so I hope it does not need autoconf magic:
http://www.opengroup.org/onlinepubs/009695399/functions/setrlimit.html

No regressions on {x86_64,x86_64-m32,i686}-fedora12-linux-gnu.

Thanks,
Jan

2010-01-11 Jan Kratochvil <jan.kratochvil@redhat.com>

* utils.c: Include sys/resource.h.
(dump_core, can_dump_core): New.
(internal_vproblem): Update the comment. Check can_dump_core while
setting dump_core_p. Replace two abort calls by dump_core calls.

--- a/gdb/utils.c
+++ b/gdb/utils.c
@@ -26,6 +26,7 @@
#include "event-top.h"
#include "exceptions.h"
#include "gdbthread.h"
+#include <sys/resource.h>

#ifdef TUI
#include "tui/tui.h" /* For tui_get_command_dimension. */
@@ -843,6 +844,40 @@ error_stream (struct ui_file *stream)
error (("%s"), message);
}

+/* Dump core trying to increase the core soft limit to hard limit first. */
+
+static void
+dump_core (void)
+{
+ struct rlimit rlim = { RLIM_INFINITY, RLIM_INFINITY };
+
+ setrlimit (RLIMIT_CORE, &rlim);
+
+ abort (); /* NOTE: GDB has only three calls to abort(). */
+}
+
+/* Check whether GDB will be able to dump core using the dump_core function. */
+
+static int
+can_dump_core (const char *reason)
+{
+ struct rlimit rlim;
+
+ /* Be quiet and assume we can dump if an error is returned. */
+ if (getrlimit (RLIMIT_CORE, &rlim) != 0)
+ return 1;
+
+ if (rlim.rlim_max == 0)
+ {
+ fprintf_unfiltered (gdb_stderr,
+ _("%s\nUnable to dump core, use `ulimit -c unlimited'"
+ " before executing GDB next time.\n"), reason);
+ return 0;
+ }
+
+ return 1;
+}
+
/* Allow the user to configure the debugger behavior with respect to
what to do when an internal problem is detected. */

@@ -893,7 +928,7 @@ internal_vproblem (struct internal_problem *problem,
case 1:
dejavu = 2;
fputs_unfiltered (msg, gdb_stderr);
- abort (); /* NOTE: GDB has only four calls to abort(). */
+ abort (); /* NOTE: GDB has only three calls to abort(). */
default:
dejavu = 3;
/* Newer GLIBC versions put the warn_unused_result attribute
@@ -902,7 +937,7 @@ internal_vproblem (struct internal_problem *problem,
does not fix this problem. This is the solution suggested
at http://gcc.gnu.org/bugzilla/show_bug.cgi?id=25509. */
if (write (STDERR_FILENO, msg, sizeof (msg)) != sizeof (msg))
- abort (); /* NOTE: GDB has only four calls to abort(). */
+ abort (); /* NOTE: GDB has only three calls to abort(). */
exit (1);
}
}
@@ -951,13 +986,18 @@ further debugging may prove unreliable.", file, line, problem->name, msg);

if (problem->should_dump_core == internal_problem_ask)
{
- /* Default (yes/batch case) is to dump core. This leaves a GDB
- `dropping' so that it is easier to see that something went
- wrong in GDB. */
- dump_core_p = query (_("%s\nCreate a core file of GDB? "), reason);
+ if (!can_dump_core (reason))
+ dump_core_p = 0;
+ else
+ {
+ /* Default (yes/batch case) is to dump core. This leaves a GDB
+ `dropping' so that it is easier to see that something went
+ wrong in GDB. */
+ dump_core_p = query (_("%s\nCreate a core file of GDB? "), reason);
+ }
}
else if (problem->should_dump_core == internal_problem_yes)
- dump_core_p = 1;
+ dump_core_p = can_dump_core (reason);
else if (problem->should_dump_core == internal_problem_no)
dump_core_p = 0;
else
@@ -966,7 +1006,7 @@ further debugging may prove unreliable.", file, line, problem->name, msg);
if (quit_p)
{
if (dump_core_p)
- abort (); /* NOTE: GDB has only four calls to abort(). */
+ dump_core ();
else
exit (1);
}
@@ -976,7 +1016,7 @@ further debugging may prove unreliable.", file, line, problem->name, msg);
{
#ifdef HAVE_WORKING_FORK
if (fork () == 0)
- abort (); /* NOTE: GDB has only four calls to abort(). */
+ dump_core ();
#endif
}
}