Is there a way to configure the directory where core dump files are placed for a specific process?
I have a daemon process written in C++ for which I would like to configure the core dump directory. Optionally the filename pattern should be configurable, too.
I know about /proc/sys/kernel/core_patte开发者_如何学JAVArn
, however this would change the pattern and directory structure globally.
Apache has the directive CoreDumpDirectory
- so it seems to be possible.
No, you cannot set it per process. The core file gets dumped either to the current working directory of the process, or the directory set in /proc/sys/kernel/core_pattern if the pattern includes a directory.
CoreDumpDirectory in apache is a hack, apache registers signal handlers for all signals that cause a core dump , and changes the current directory in its signal handler.
/* handle all varieties of core dumping signals */
static void sig_coredump(int sig)
{
apr_filepath_set(ap_coredump_dir, pconf);
apr_signal(sig, SIG_DFL);
#if AP_ENABLE_EXCEPTION_HOOK
run_fatal_exception_hook(sig);
#endif
/* linuxthreads issue calling getpid() here:
* This comparison won't match if the crashing thread is
* some module's thread that runs in the parent process.
* The fallout, which is limited to linuxthreads:
* The special log message won't be written when such a
* thread in the parent causes the parent to crash.
*/
if (getpid() == parent_pid) {
ap_log_error(APLOG_MARK, APLOG_NOTICE,
0, ap_server_conf,
"seg fault or similar nasty error detected "
"in the parent process");
/* XXX we can probably add some rudimentary cleanup code here,
* like getting rid of the pid file. If any additional bad stuff
* happens, we are protected from recursive errors taking down the
* system since this function is no longer the signal handler GLA
*/
}
kill(getpid(), sig);
/* At this point we've got sig blocked, because we're still inside
* the signal handler. When we leave the signal handler it will
* be unblocked, and we'll take the signal... and coredump or whatever
* is appropriate for this particular Unix. In addition the parent
* will see the real signal we received -- whereas if we called
* abort() here, the parent would only see SIGABRT.
*/
}
It is possible to make it using the "|command" mechanism of the core_pattern file. The executed command can create the directories and files as needed. The command can be passed the following specifiers in the parameters (cf. man 5 core):
%% a single % character
%c core file size soft resource limit of crashing process
%d dump mode—same as value returned by prctl(2) PR_GET_DUMPABLE
%e executable filename (without path prefix)
%E pathname of executable, with slashes ('/') replaced by exclamation marks ('!')
%g (numeric) real GID of dumped process
%h hostname (same as nodename returned by uname(2))
%i TID of thread that triggered core dump, as seen in the PID namespace in which the thread resides
%I TID of thread that triggered core dump, as seen in the initial PID namespace
%p PID of dumped process, as seen in the PID namespace in which the process resides
%P PID of dumped process, as seen in the initial PID namespace
%s number of signal causing dump
%t time of dump, expressed as seconds since the Epoch, 1970-01-01 00:00:00 +0000 (UTC)
%u (numeric) real UID of dumped process
For example, it possible to create a script (e.g. named crash.sh) as follow:
#!/bin/bash
# $1: process number on host side (%P)
# $2: program's name (%e)
OUTDIR=/tmp/core/$2
OUTFILE="core_$1"
# Create a sub-directory in /tmp
mkdir -p "$OUTDIR"
# Redirect stdin in a per-process file:
cat > "$OUTDIR"/"$OUTFILE"
exit 0
In the shell:
$ chmod +x crash.sh
$ mv crash.sh /tmp # Put the script in some place
$ sudo su
# echo '|/tmp/crash.sh %P %e' > /proc/sys/kernel/core_pattern
# cat /proc/sys/kernel/core_pattern
|/tmp/crash.sh %P %e
# exit
$
Create an example program which crashes (e.g. fail.c):
int main(void)
{
char *ptr = (char *)0;
*ptr = 'q';
return 0;
}
Compile the program (make several executables) and adjust the core file size in the current shell:
$ gcc fail.c -o fail1
$ gcc fail.c -o fail2
$ ulimit -c
0
$ ulimit -c unlimited
$ ulimit -c
unlimited
Run the failing programs several times to have multiple processes ids:
$ ./fail1
Segmentation fault (core dumped)
$ ./fail2
Segmentation fault (core dumped)
$ ./fail1
Segmentation fault (core dumped)
$ ./fail2
Segmentation fault (core dumped)
Look at /tmp where the core_pattern redirect the core dumps:
$ ls -l /tmp/core
total 8
drwxrwxrwx 2 root root 4096 nov. 3 15:57 fail1
drwxrwxrwx 2 root root 4096 nov. 3 15:57 fail2
$ ls -l /tmp/core/fail1/
total 480
-rw-rw-rw- 1 root root 245760 nov. 3 15:57 core_10606
-rw-rw-rw- 1 root root 245760 nov. 3 15:57 core_10614
$ ls -l /tmp/core/fail2
total 480
-rw-rw-rw- 1 root root 245760 nov. 3 15:57 core_10610
-rw-rw-rw- 1 root root 245760 nov. 3 15:57 core_10618
精彩评论