-
-
Save oneman/9571751 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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]