Register for dump notifications
#include <sys/dcmd_dumper.h> #define DCMD_DUMPER_NOTIFYEVENT __DIOT(_DCMD_MISC, DUMPER_NOTIFYEVENT, struct sigevent)
| Argument | Value |
|---|---|
| filedes | A file descriptor for the dumper that you obtained by opening /proc/dumper |
| dcmd | DCMD_DUMPER_NOTIFYEVENT |
| dev_data_ptr | A pointer to a struct sigevent |
| n_bytes | sizeof(struct sigevent) |
| dev_info_ptr | NULL |
This command registers a program for dump notifications.
A struct sigevent that's filled in to indicate what type of notification you want.
None.
#include <stdio.h>
#include <stdlib.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 <errno.h>
#include <string.h>
#include <sys/neutrino.h>
#include <sys/procfs.h>
#ifndef NOFD
#define NOFD -1
#endif
int dumper_notify_attach(struct sigevent *devent)
{
int dumper_fd;
dumper_fd = open("/proc/dumper",O_RDONLY);
/* Only registered events can be used by default. */
if (MsgRegisterEvent(devent, dumper_fd) == -1) {
perror("MsgRegisterEvent");
}
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;
}
#ifndef ARRAY_SIZE
#define ARRAY_SIZE(x) ((sizeof(x))/sizeof(*(x)))
#endif
#define DUMP_PULSE_CODE 0x50
int dumper_get_dumppath(char *buf, size_t buf_len, int fd, int pid)
{
dump_info_t dinfo;
iov_t in_iov[1], out_iov[1];
if (buf==NULL || buf_len==0 || fd==NOFD) {
errno=EINVAL;
return -1;
}
dinfo.i.pid = pid;
SETIOV(in_iov+0, &dinfo.i, sizeof(dinfo.i));
SETIOV(out_iov+0, buf, buf_len);
return devctlv(fd, DCMD_DUMPER_GETPATH, ARRAY_SIZE(in_iov), ARRAY_SIZE(out_iov),
in_iov, out_iov, NULL);
}
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);
// Make this event updateable to allow the dumper to put pid data
// into 'value.sival_int' field of the pulse structure.
SIGEV_MAKE_UPDATEABLE(&devent);
dumper_fd=dumper_notify_attach(&devent);
if (dumper_fd==-1) {
perror("ERROR: opening /proc/dumper");
exit( -1 );
}
for (;;) {
char buf[PATH_MAX];
int ret;
// Blocks waiting for a pulse
rcvid = MsgReceivePulse(dp_chid, &gpulse, sizeof(gpulse), NULL);
if(rcvid < 0){
perror("MsgReceivePulse");
continue;
}
switch (gpulse.code) {
case DUMP_PULSE_CODE: // something died
pid = gpulse.value.sival_int;
ret=dumper_get_dumppath(buf, sizeof(buf), dumper_fd, pid);
if (ret < 0) {
fprintf(stderr, "devctl(DCMD_DUMPER_GETPATH) : %s\n",
strerror(ret));
buf[0]='\0';
}
fprintf(stderr, "Received Dump Pulse code %"PRId8"\n",
gpulse.code);
fprintf(stderr, "Process Pid %d dumped to %s\n",
pid, buf);
break;
default:
fprintf(stderr, "Unknown pulse code: %"PRId8"\n",
gpulse.code);
break;
}
}
if (dumper_fd >=0)
{
devctl(dumper_fd, DCMD_DUMPER_REMOVEALL, NULL, 0, NULL);
/* This would have worked too, because we attached only one event:
devctl(dumper_fd, DCMD_DUMPER_REMOVEEVENT, NULL, 0, NULL);
*/
close(dumper_fd);
}
if (dp_coid >=0)
ConnectDetach(dp_coid);
if (dp_chid >=0)
ChannelDestroy(dp_chid);
exit(0);
}
DCMD_DUMPER_GETPATH, DCMD_DUMPER_REMOVEALL, DCMD_DUMPER_REMOVEEVENT
devctl() in the QNX Neutrino C Library Reference
dumper in the Utilities Reference