#include <sys/epoll.h>

#include <signal.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <time.h>
#include <unistd.h>

#include <linux/unistd.h>
#include <linux/types.h>

#define _syscall2(type,name,type1,arg1,type2,arg2) \
type name (type1 arg1, type2 arg2) \
{\
	return syscall(__NR_##name, arg1, arg2);\
}

_syscall2(int, signalfd, int, sig, int, flags);

#if 1
#define ulog(f, a...) fprintf(stderr, f, ##a)
#else
#define ulog(f, a...)
#endif
#define ulog_err(f, a...) ulog(f ": %s [%d].\n", ##a, strerror(errno), errno)

static void sig_handler(int signo)
{
	printf("%s, signo: %d.\n", __func__, signo);
}

static int epoll_signal_init(int ctl_fd, int sig, int flags)
{
	int fd;
	struct epoll_event event;

	fd = signalfd(sig, flags);
	if (fd < 0) {
		ulog_err("Failed to bind signal: %d, flags: %d", sig, flags);
		return fd;
	}

	event.events = EPOLLIN;
	event.data.fd = fd;

	if (epoll_ctl(ctl_fd, EPOLL_CTL_ADD, fd, &event) < 0) {
		ulog_err("Failed to perform control ADD operation: fd: %d", fd);
		return -1;
	}

	return 0;
}

int main()
{
	int err, ctl_fd, i;
	struct epoll_event event[256];

	ctl_fd = epoll_create(10);
	if (ctl_fd < 0) {
		ulog_err("Failed to create epoll control file descriptor");
		return -1;
	}

	signal(SIGUSR1, sig_handler);
	signal(SIGUSR2, sig_handler);
	
	err = epoll_signal_init(ctl_fd, SIGUSR1, 1);
	if (err)
		return err;

	err = epoll_signal_init(ctl_fd, SIGUSR2, 0);
	if (err)
		return err;

	ulog("%s: pid: %d\n", __func__, getpid());

	kill(getpid(), SIGUSR1);
	kill(getpid(), SIGUSR2);

	while (1) {
		err = epoll_wait(ctl_fd, event, 256, 10000);
		if (err < 0) {
			ulog_err("Failed to wait for events");
			continue;
		}

		if (err == 0)
			continue;

		for (i=0; i<err; ++i)
			printf("Dequeued signal, fd: %u.\n", event[i].data.fd);
	}

	return 0;
}

