Dump the postmortem state of a program (QNX)
dumper [-d path] [-m] [-n] [-P] [-p pid] [-s size[G|M|K]]
[-t] [-v] [-w] [-z level] &
Neutrino
The dumper utility runs in the background and provides a postmortem dump service for all processes. Whenever a program terminates abnormally, a dump of the current state of the program is written to disk. The dump filename is the same as the program name with a .core extension. For example, if the program name is experiment, the dump is written to experiment.core in your home directory.
![]() |
On a QNX Momentics system, dumper starts with dumper -d /var/dumps. |
You can use the -d option to force all dumps into a directory other than /var/dumps.
![]() |
Dump files can be large, so make sure the destination filesystem has lots of space. |
The -p option lets you get a dump immediately for a particular process. If you specify -p, dumper doesn't run in the background, but exits right away.
You can use a debugger such as gdb to examine a dump file:
gdb program_binary program_core
For example:
gdb /usr/photon/bin/pterm /var/dumps/pterm.core
A program may terminate in one of two ways: it may exit cleanly under its own control, returning an exit status, or it may be forcibly terminated by the receipt of a signal that it isn't prepared to handle. In the latter case, dumper writes a dump file for the following set of signals:
| Signal | Description |
|---|---|
| SIGABRT | Program-called abort function |
| SIGBUS | Parity error |
| SIGEMT | EMT instruction (emulation trap). Note that SIGEMT and SIGDEADLK refer to the same signal. |
| SIGFPE | Floating-point error or division by zero |
| SIGILL | Illegal instruction executed |
| SIGQUIT | Quit |
| SIGSEGV | Segmentation violation |
| SIGSYS | Bad argument to a system call |
| SIGTRAP | Trace trap (not reset when caught) |
| SIGXCPU | Exceeded the CPU limit |
You can force the dump of a running program by setting one of the preceding signals, assuming that the program isn't masking or handling the signal itself. For example, to force a dump using the kill command and a process ID (pid):
kill -SIGABRT pid
To force a dump using the slay utility and the process name:
slay -s SIGABRT process_name
Start dumper, with dump files to be written to the default directory:
dumper &
Start dumper, with dump files to be placed in the directory /home/dumps:
dumper -d /home/dumps &
Register for dump notifications:
#include <stdio.h>
#include <stdint.h>
#include <inttypes.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/dcmd_dumper.h>
#include <fcntl.h>
#include <unistd.h>
#include <devctl.h>
#include <sys/neutrino.h>
int
dumper_notify_attach(struct sigevent *devent)
{
int dumper_fd;
dumper_fd = open("/proc/dumper",O_RDONLY);
if (dumper_fd >= 0) {
devctl(dumper_fd, DCMD_DUMPER_NOTIFYEVENT, devent, sizeof(*devent), NULL);
fcntl(dumper_fd, F_SETFD, FD_CLOEXEC);
} else {
dumper_fd = -1;
}
return dumper_fd;
}
#define DUMP_PULSE_CODE 0x50
int
main(int argc, const char *argv[], const char*envp[]){
int dp_chid=-1;
int dp_coid=-1;
struct sigevent devent;
struct _pulse gpulse;
int dumper_fd=-1;
int rcvid;
pid_t pid;
// create death pulses channel
dp_chid = ChannelCreate(_NTO_CHF_FIXED_PRIORITY);
if(dp_chid==-1){
perror("ERROR: ChannelCreate");
exit( -1 );
}
dp_coid = ConnectAttach(0, 0, dp_chid, _NTO_SIDE_CHANNEL, _NTO_COF_CLOEXEC);
if(dp_coid==-1){
perror("ERROR: ConnectAttach");
exit( -1 );
}
SIGEV_PULSE_INIT(&devent, dp_coid, sched_get_priority_max(SCHED_RR), DUMP_PULSE_CODE, -1);
dumper_fd=dumper_notify_attach(&devent);
if(dumper_fd==-1){
perror("ERROR: opening /proc/dumper");
exit( -1 );
}
for (;;) {
// Blocks waiting for a pulse
rcvid = MsgReceivePulse(dp_chid, &gpulse, sizeof(gpulse),NULL);
switch (gpulse.code) {
case DUMP_PULSE_CODE: // something died
pid = gpulse.value.sival_int;
fprintf(stderr, "Received Death Pulse code %"PRId8"\n" , gpulse.code);
fprintf(stderr, "Process Pid %d died abnormally\n" , pid);
break;
default:
fprintf(stderr, "Unknown pulse code: %"PRId8"\n" , gpulse.code);
break;
}
}
if (dumper_fd >=0)
close(dumper_fd);
if (dp_coid >=0)
ConnectDetach(dp_coid);
if (dp_chid >=0)
ChannelDestroy(dp_chid);
exit(0);
}
The dumper utility normally doesn't terminate. However, it may terminate if it encounters an error on startup (for instance, if it wasn't run by root) or if it receives a signal.