In comp.unix.internals Paul Hite <p...@access5.digex.net> wrote:
: In article <3520D772....@pia.bt.co.uk>,
: Simon Courtenage <si...@pia.bt.co.uk> wrote:
:>Usually, when a program ends abnormally, it dumps a memory image
:>to a file named 'core'. But is it possible to have it dump to
:>a file with a different name, e.g., core.programname???
: If you have the source code to the program that is aborting it's
: possible but rough. Programs abort and dump core because they
: receive signals from the kernel. You can install a signal handler to
: catch all of those signals. The program might be aborting because it
: overflowed its stack area. So you need to use sigspace or sigstack to
: provide a stack for your handler.
: When the signal arrives the stack handler should create a unique directory
: under the current directory and cd there. Then disinstall the handler and
: fork. The child should sent the original signal to itself which will
: cause it to dump to a file named "core". The parent waits for the child
: to die and then links core to ../whatever then it unlinks core cd's to ..
: and rmdir's the directory and exits.
: What could be simpler? 8-)
Nothing!
Here is some code I wrote some years ago for a project.
It works on SunOS 4.1.x ONLY.
/ Lesley
#pragma ident "@(#) got_signal.c 1.1 94/03/17 Lesley Stoa CAP Programator"
/*
*--------------------------------------------------------------------------
*
* Name got_signal.c
*
*
* Original: 1994-03-17 Lesley Stoa, Cap Gemini Sweden AB.
* Email: Lesley.S...@capgemini.se
*
* Description: Creates a uniq core-file when a program crash.
*
*
*-------------------------------------------------------------------------
README for got_signal: A routine to create uniq core-files when
a program crash.
1. What it does ?
When an application that uses got_signal receives one of the signals
SIGQUIT, SIGILL, SIGABRT, SIGBUS or SIGSEGV
it dumps the core of the application to a core file of the following
format:
DIR/core.<hostname>.<programname>.YYMMDD_HHMMSS
where DIR is either $COREDEV, $HOME or /tmp depending on if the
environment variables exist and/or directory is writeable.
Example: COREDEV = /var/corefiles, hostanme = hilda4,
application = browser, date = 940317 time = 11:34:22
The name of the core file created is:
/var/corefiles/core.hilda4.browser.940317_113422
2. What info does the user get when the program crashes ?
Normaly when an application crashes, the only info written on the screen
is something like:
Segmentation fault (core dumped)
When using got_signal the following is written on the screen
when an application as in the example above receives SIGSEGV:
browser: Segmentation fault (core dumped to file
/var/corefiles/core.hilda4.browser.940317_113422)
3. How do I use got_signal ?
a) First compile got_signal.c: (Don't try to understand the code!!)
cc -c got_signal.c (Don't use the -O flag!!!)
b) Add the the following code to your C++ or C main code:
extern void set_signalcatch (); // Declare set_signalcatch
main( int argc, char *argv[])
{
// Declarations
set_signalcatch (); // Setup to catch signals
// Rest of your code
c) When linking, include got_signal.o in your link command.
d) READY! Run your application.
4. Who wrote got_signal.c ?
got_signal.c is written by Lesley Stoa, Cap Gemini Sweden AB
**************************************************************************/
#include <stdio.h>
#include <errno.h>
#include <signal.h>
#include <time.h>
#include <unistd.h>
#include <sys/ptrace.h>
#include <sys/param.h>
#include <sys/wait.h>
#include <sys/core.h>
#include <machine/reg.h>
int
got_signal ( sig, code, scp )
int sig, code;
struct sigcontext *scp;
{
int pid, mask, i, j;
char corefile[128], corefile2[128];
char hostname[20];
char *cur_path, *getenv();
struct regs the_regs, prev_regs;
struct core this_core;
FILE *fp;
time_t timenow;
struct tm *tm;
signal ( sig, SIG_DFL );
signal ( SIGCHLD, SIG_DFL );
mask = sigblock ( 0 );
if ( mask & sigmask ( sig ) ) {
mask ^= sigmask ( sig );
sigsetmask ( mask );
}
cur_path = getenv ("COREDEV");
if (!cur_path) {
cur_path = getenv ("HOME");
} else if (access (cur_path, W_OK)) {
cur_path = getenv ("HOME");
}
if (!cur_path) {
cur_path = "/tmp";
} else if (access (cur_path, W_OK)) {
cur_path = "/tmp";
}
if (setuid (getuid ()) != 0) {
perror ("Setuid");
}
pid = fork ();
if (pid > 0) {
sleep (1);
if ( ptrace ( PTRACE_ATTACH, pid, 0, 0 ) ) {
perror ( "Error in ptrace ATTACH" );
exit ( 1 );
}
while ( wait ( 0 ) != pid );
if (ptrace ( PTRACE_GETREGS, pid, &the_regs, 0 )) {
perror ( "Error in ptrace GETREGS" );
exit ( 1 );
}
prev_regs = the_regs;
the_regs.r_g1 = scp->sc_g1;
the_regs.r_o0 = scp->sc_o0;
the_regs.r_pc = scp->sc_pc;
the_regs.r_npc = scp->sc_npc;
the_regs.r_sp = scp->sc_sp;
the_regs.r_psr = scp->sc_psr;
if (ptrace ( PTRACE_SETREGS, pid, &the_regs, 0 )) {
perror ( "Error in ptrace SETREGS" );
exit ( 1 );
}
gethostname (hostname, 19);
timenow = time(0);
tm = localtime (&timenow);
sprintf (corefile, "%s/core.%s.%d", cur_path, hostname, pid);
if ( ptrace ( PTRACE_DUMPCORE, pid, corefile, 0 ) ) {
perror ( "Error in ptrace DUMPCORE" );
exit ( 1 );
}
if (ptrace ( PTRACE_SETREGS, pid, &prev_regs, 0 )) {
perror ( "Error in ptrace SETREGS" );
exit ( 1 );
}
if ( ptrace ( PTRACE_DETACH, pid, 1, 0 ) ) {
perror ( "Error in ptrace DETACH" );
exit ( 1 );
}
kill ( pid, 9 );
while ( wait ( 0 ) != pid );
fp = fopen ( corefile, "r+" );
if ( fp ) {
if ( fread ( &this_core, sizeof ( struct core ), 1, fp ) ) {
this_core.c_signo = sig;
rewind ( fp );
fwrite ( &this_core, sizeof ( struct core ), 1, fp );
}
fclose ( fp );
} else {
strcpy (this_core.c_cmdname, "unknown");
}
sprintf (corefile2, "%s/core.%s.%s.%02d%02d%02d_%02d%02d%02d",
cur_path, hostname, this_core.c_cmdname,
tm->tm_year,
tm->tm_mon + 1,
tm->tm_mday,
tm->tm_hour,
tm->tm_min,
tm->tm_sec
);
rename (corefile, corefile2);
fprintf (stderr, "%s: ", this_core.c_cmdname);
switch (sig) {
case SIGQUIT:
fprintf (stderr, "Quit");
break;
case SIGILL:
fprintf (stderr, "Illegal instruction");
break;
case SIGABRT:
fprintf (stderr, "IOT trap");
break;
case SIGBUS:
fprintf (stderr, "Bus error");
break;
case SIGSEGV:
fprintf (stderr, "Segmentation fault");
break;
default:
fprintf (stderr, "Crash");
break;
}
fprintf ( stderr, " (core dumped to file %s)\n", corefile2);
exit ( 1 );
} else if (pid == 0) {
asm ( "restore" );
asm ( "ld [%fp + 0x48], %i0" );
asm ( "ld [%sp + 0xe4], %l1" );
asm ( "ld [%i0 + 0x14], %o0" );
asm ( "ldd [%sp + 0xe8], %g2" );
asm ( "ldd [%sp + 0xf0], %g4" );
asm ( "ldd [%sp + 0xf8], %g6" );
asm ( "mov %l1, %y" );
asm ( "restore %g0, 0x8b, %g1" );
while ( 1 );
} else {
/** Can't fork make a standard core file **/
kill (getpid (), sig);
}
return 0;
}
asm(".seg \"text\"");
asm(".proc 020");
asm(".global _set_signalcatch__Fv");
asm("_set_signalcatch__Fv:"); /* C++ hook */
asm(".seg \"data\"");
void
set_signalcatch ()
{
signal ( SIGQUIT, got_signal );
signal ( SIGILL, got_signal );
signal ( SIGABRT, got_signal );
signal ( SIGBUS, got_signal );
signal ( SIGSEGV, got_signal );
return;
}
--
Lesley Stoa
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
Computer consultant Voice : +46 31 335 46 00
Cap Gemini Sverige AB Mobile: +46 705 47 38 52
Div. Utilities and Telecom FAX : +46 31 335 47 50
Gothenburg, Sweden E-mail: Lesley.S...@capgemini.se
-------------------------------------------------------------
At the moment working for Voice : +46 31 746 26 04
EHS/SU EHPT AB FAX : +46 31 746 28 40
Molndal, Sweden E-mail: qhss...@aom.ericsson.se
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=