DCMD_DUMPER_NOTIFYEVENT

QNX SDP8.0Devctl and Ioctl CommandsDeveloper

Register for dump notifications

Synopsis:

#include <sys/dcmd_dumper.h>

#define DCMD_DUMPER_NOTIFYEVENT __DIOT(_DCMD_MISC, DUMPER_NOTIFYEVENT, struct sigevent)

Arguments to devctl():

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

Description:

This command registers a program for dump notifications.

Input:

A struct sigevent that's filled in to indicate what type of notification you want. The application must register the event by calling MsgRegisterEvent() with the file descriptor obtained from opening the dumper process.

Set the event to be updateable with SIGEV_MAKEUPDATEABLE to receive the process ids (pids) of the programs that were dumped in the value field of the delivered event.

Output:

None.

Example:

 
#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 rc;
    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
        rc = MsgReceivePulse(dp_chid, &gpulse, sizeof(gpulse), NULL);
        if(rc < 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 != EOK) {
                    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)
    {
       

        /* Cancel the notification request */
        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);
}

See also:

DCMD_DUMPER_GETPATH, DCMD_DUMPER_REMOVEEVENT

devctl() in the QNX OS C Library Reference

dumper in the Utilities Reference

Page updated: