Skip to content

Instantly share code, notes, and snippets.

@oneman
Forked from dsheeler/kr_signalfd_test.c
Last active August 29, 2015 13:57
Show Gist options
  • Save oneman/9571751 to your computer and use it in GitHub Desktop.
Save oneman/9571751 to your computer and use it in GitHub Desktop.
#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
#include <unistd.h>
#include <signal.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/signalfd.h>
#include <sys/epoll.h>
#include <sys/timerfd.h>
#define KR_EPOLL_MAX_EVENTS 10
#define KR_POPEN_BUF_SIZE 8192
static void handle_error(const char *msg) {
perror(msg);
exit(EXIT_FAILURE);
}
static int kr_setup_signalfd() {
sigset_t mask;
int sfd;
int flags;
sigemptyset(&mask);
sigfillset(&mask);
if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1) {
handle_error("sigprocmask");
}
flags = SFD_NONBLOCK | SFD_CLOEXEC;
sfd = signalfd(-1, &mask, flags);
if (sfd == 1) {
handle_error("signalfd");
}
return sfd;
}
static void epoll_add_fd(int epollfd, int fd) {
struct epoll_event ev;
ev.events = EPOLLIN;
ev.data.fd = fd;
if (epoll_ctl(epollfd, EPOLL_CTL_ADD, fd, &ev) == -1) {
handle_error("epoll_ctl");
}
}
static int kr_setup_epollfd() {
int epollfd;
epollfd = epoll_create1(EPOLL_CLOEXEC);
if (epollfd == -1) {
handle_error("epoll_create");
}
return epollfd;
}
static int process_signal_event(struct epoll_event *event) {
struct signalfd_siginfo sig_info;
int sig_size = sizeof(struct signalfd_siginfo);
int to_read = sig_size;
ssize_t did_read;
int count = 0;
for (;;) {
did_read = read(event->data.fd, &sig_info, to_read);
if (did_read == -1) {
if (errno != EAGAIN) {
handle_error("signal read");
}
break;
}
if (did_read < to_read) {
to_read -= did_read;
continue;
}
to_read = sig_size;
++count;
if (sig_info.ssi_signo == SIGINT) {
printf("Got SIGINT\n");
return -1;
} else if (sig_info.ssi_signo == SIGTERM) {
printf("Got SIGTERM\n");
return -1;
} else {
printf("Got a signal\n");
}
}
return count;
}
static void print_elapsed_time(void) {
static struct timespec start;
struct timespec curr;
static int first_call = 1;
int secs, nsecs;
if (first_call) {
first_call = 0;
if (clock_gettime(CLOCK_MONOTONIC, &start) == -1)
handle_error("clock_gettime");
}
if (clock_gettime(CLOCK_MONOTONIC, &curr) == -1)
handle_error("clock_gettime");
secs = curr.tv_sec - start.tv_sec;
nsecs = curr.tv_nsec - start.tv_nsec;
if (nsecs < 0) {
secs--;
nsecs += 1000000000;
}
printf("%d.%03d: ", secs, (nsecs + 500000) / 1000000);
}
static int kr_setup_timerfd() {
struct itimerspec new_value;
int tfd;
int flags;
new_value.it_value.tv_sec = 1;
new_value.it_value.tv_nsec = 0;
new_value.it_interval.tv_sec = 1;
new_value.it_interval.tv_nsec = 0;
flags = TFD_NONBLOCK | TFD_CLOEXEC;
tfd = timerfd_create(CLOCK_MONOTONIC, flags);
if (tfd == -1) {
handle_error("timerfd_create");
}
if (timerfd_settime(tfd, 0, &new_value, NULL) == -1) {
handle_error("timerfd_settime");
}
return tfd;
}
static void process_timerfd_event(int tfd) {
uint64_t nexp;
int ret;
struct itimerspec timer_time;
nexp = 0;
ret = read(tfd, &nexp, sizeof(nexp));
if (ret == -1) {
perror("read timerfd");
}
printf("Timer expired\n");
ret = timerfd_gettime(tfd, &timer_time);
if (ret == -1) {
perror("timerfd_gettime");
}
}
static FILE *launch_get_media_info(const char *url) {
FILE *fp;
char cmd[512];
snprintf(cmd, 512, "kr_quvi_test %s", url);
//snprintf(cmd, 512, "ls");
cmd[511] = '\0';
fp = popen(cmd, "r");
if (fp == NULL) {
handle_error("dang popen failed\n");
}
return fp;
}
static int process_popen_event(struct epoll_event *event) {
char output[KR_POPEN_BUF_SIZE];
int to_read = KR_POPEN_BUF_SIZE;
ssize_t did_read;
if (event->events & EPOLLIN) {
printf("Got EPOLLIN\n");
} else if (event->events & EPOLLERR) {
printf("Got EPOLLERR\n");
} else if (event->events & EPOLLHUP) {
printf("Got EPOLLHUP\n");
} else {
printf("Got other EPOLL event\n");
}
for (;;) {
did_read = read(event->data.fd, output, to_read);
printf("wft %zd\n", did_read);
if ((did_read == 0) || (did_read == -1)) {
return -1;
break;
}
fprintf(stdout, "%s", output);
}
return 0;
}
int main(int argc, char **argv) {
int epollfd;
struct epoll_event events[KR_EPOLL_MAX_EVENTS];
int ret;
int nfds, n;
int sfd;
int tfd;
int done = 0;
int exp = 0;
int max_exp = 20;
FILE *quvi_proc;
int qfd;
epollfd = kr_setup_epollfd();
sfd = kr_setup_signalfd();
epoll_add_fd(epollfd, sfd);
tfd = kr_setup_timerfd();
epoll_add_fd(epollfd, tfd);
print_elapsed_time();
printf("Starting timer!\n");
if (argc == 2) {
quvi_proc = launch_get_media_info(argv[1]);
} else {
quvi_proc = launch_get_media_info("https://www.youtube.com/watch?v=DBNy4WVm3D4");
}
qfd = fileno(quvi_proc);
epoll_add_fd(epollfd, qfd);
while (!done) {
nfds = epoll_wait(epollfd, events, KR_EPOLL_MAX_EVENTS, -1);
if (nfds == -1) {
handle_error("epoll_pwait");
}
print_elapsed_time();
printf("Mainloop got %d events!\n", nfds);
for (n = 0; n < nfds; n++) {
if (events[n].data.fd == sfd) {
ret = process_signal_event(&events[n]);
if (ret == -1) done = 1;
} else if (events[n].data.fd == tfd) {
process_timerfd_event(tfd);
++exp;
if (exp == max_exp) {
done = 1;
}
} else {
ret = process_popen_event(&events[n]);
if (ret == -1) done = 1;
}
}
}
printf("Times up! Goodbye.\n");
ret = pclose(quvi_proc);
printf("pclose ret %d", ret);
/* lets close things */
if (close(tfd)) {
perror("close tfd");
}
if (close(epollfd)) {
perror("close epollfd");
}
if (close(sfd)) {
perror("close sfd");
}
return 0;
}
@Favorwilliams
Copy link

My Pleasure to write you,
My name is Favor Williams,
My email address is
( [email protected])
Am interested to know
more about you,
Contact me for my
photo and other
important issue via,

[email protected]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment