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