I wrote a quick test application for the Linux timerfd and signalfd
system calls, which let you handle timers and signals as just another fd
in a poll loop.  The test application polls a 1-second timerfd, a
signalfd, and stdin, and just dumps the data to stdout.  A couple of
people expressed an interest in seeing this test program, so I've
attached it.

Due to a bug in the glibc headers for timerfd (reported and now fixed
upstream), compiling this code in pure c99 mode doesn't work.  Try this
for now: "gcc -std=gnu99 -Wall polltest.c -o polltest".  When you run
./polltest, it'll go into a loop polling the three fds, and print all
data that becomes available.

When the timerfd goes off every second, you'll see 8 bytes representing
the number of times the timer went off.  Normally that number will
remain 1, but if you "killall -STOP polltest" from another terminal,
wait a bit, and then resume it with fg, you'll see a larger number of
expirations.

If you send polltest a signal, it'll print a large data structure,
described in "man signalfd".  That structure starts with the signal
number, which you can look up in "man 7 signal".  (If you try the
experiment I mentioned above of stopping polltest for a while, you'll
see one of these structures when polltest resumes; that structure
indicates SIGCONT, which you *can* actually catch, unlike SIGSTOP.)

If you type at polltest (and hit enter, since I didn't switch off line
buffering), it'll dump out the bytes you typed.

Note that since polltest catches all signals, you can't kill it with
Ctrl-C or Ctrl-\, and you can't background it with Ctrl-Z.  You'll need
to SIGKILL it; try "killall -9 polltest" from another terminal.

- Josh Triplett
#include <poll.h>
#include <signal.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/signalfd.h>
#include <sys/timerfd.h>
#include <unistd.h>

#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))

static void die(char *msg)
{
    printf("%s\n", msg);
    exit(1);
}

static void perror_die(char *msg)
{
    perror(msg);
    exit(1);
}

int main(int argc, char *argv[])
{
    int tfd = timerfd_create(CLOCK_MONOTONIC, 0);
    if (tfd < 0)
        perror_die("timerfd_create");
    if (timerfd_settime(tfd, 0, &(struct itimerspec){ { 1, 0 }, { 1, 0} }, NULL) < 0)
        perror_die("timerfd_settime");

    sigset_t sigs;
    sigfillset(&sigs);
    int sfd = signalfd(-1, &sigs, 0);
    if (sfd < 0)
        perror_die("signalfd");
    if (sigprocmask(SIG_SETMASK, &sigs, NULL) < 0)
        perror_die("sigprocmask");
    struct pollfd pollfds[] = {
        { tfd, POLLIN },
        { sfd, POLLIN },
        { 0, POLLIN },
    };
    uint8_t buf[4096];

    while (1) {
        if (poll(pollfds, ARRAY_SIZE(pollfds), -1) < 0)
            perror_die("poll");
        for (unsigned i = 0; i < ARRAY_SIZE(pollfds); i++)
            if (pollfds[i].revents & POLLIN) {
                printf("Data on fd %d:", pollfds[i].fd);
                ssize_t bytes_read = read(pollfds[i].fd, buf, sizeof(buf));
                if (bytes_read < 0)
                    perror_die("read");
                else if (bytes_read == 0)
                    die("EOF?");
                for (unsigned b = 0; b < bytes_read; b++)
                    printf("%c0x%02x", b % 16 ? ' ' : '\n', buf[b]);
                printf("\n\n");
            }
    }
}
_______________________________________________
psas-avionics mailing list
psas-avionics@lists.psas.pdx.edu
http://lists.psas.pdx.edu/mailman/listinfo/psas-avionics

Reply via email to