Comment by tlsalmin
1 month ago
First nitpick:
static int pipe_fd[2] = {0};
0 is valid fd, so I recommend initializing fds to -1.
signalfd was just off-hand mentioned, but for writing anything larger, like lets say a daemon process, it keeps things close to all the other events being reacted to. E.g.
#include <signal.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/timerfd.h>
#include <sys/signalfd.h>
#include <sys/epoll.h>
static int signalfd_init(void)
{
sigset_t sigs, oldsigs;
int sfd = -1;
sigemptyset(&sigs);
sigemptyset(&oldsigs);
sigaddset(&sigs, SIGCHLD);
if (!sigprocmask(SIG_BLOCK, &sigs, &oldsigs))
{
sfd = signalfd(-1, &sigs, SFD_CLOEXEC | SFD_NONBLOCK);
if (sfd != -1)
{
// Success
return sfd;
}
else
{
perror("signalfd");
}
sigprocmask(SIG_SETMASK, &oldsigs, NULL);
}
else
{
perror("sigprocmask");
}
return -1;
}
static int timerfd_init(void)
{
int tfd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK | TFD_CLOEXEC);
if (tfd != -1)
{
struct itimerspec tv =
{
.it_value =
{
.tv_sec = 5
}
};
if (!timerfd_settime(tfd, 0, &tv, NULL))
{
return tfd;
}
else
{
perror("timerfd_settime");
}
close(tfd);
}
else
{
perror("timerfd_create");
}
return -1;
}
static int epoll_init(int sfd, int tfd)
{
int efd;
if (!sfd || !tfd)
{
return -1;
}
efd = epoll_create1(EPOLL_CLOEXEC);
if (efd != -1)
{
struct epoll_event ev[2] =
{
{
.events = EPOLLIN,
.data =
{
.fd = sfd,
}
},
{
.events = EPOLLIN,
.data =
{
.fd = tfd
}
}
};
if (!epoll_ctl(efd, EPOLL_CTL_ADD, sfd, &ev[0]) &&
!epoll_ctl(efd, EPOLL_CTL_ADD, tfd, &ev[1]))
{
return efd;
}
else
{
perror("epoll_ctl");
}
close(efd);
}
else
{
perror("epoll_create1");
}
return -1;
}
int main(int argc, char *argv[])
{
int exit_value = EXIT_FAILURE;
int sfd = signalfd_init(),
tfd = timerfd_init(),
efd = epoll_init(sfd, tfd);
if (sfd != -1 && tfd != -1 && efd != -1)
{
int child_pid = fork();
if (child_pid != -1)
{
if (!child_pid)
{
argv += 1;
if (-1 == execvp(argv[0], argv)) {
exit(EXIT_FAILURE);
}
__builtin_unreachable();
}
else
{
int err;
struct epoll_event ev;
while ((err = epoll_wait(efd, &ev, 1, -1)) > 0)
{
if (ev.data.fd == tfd)
{
// Read the signalfd for the possible SIGCHLD and
exit_value = EXIT_SUCCESS;
}
else if (ev.data.fd == tfd)
{
// Timer triggered, kill the child process.
}
}
if (err == -1)
{
perror("epoll_wait");
}
}
}
else
{
perror("fork");
}
}
close(sfd);
close(tfd);
close(efd);
exit(exit_value);
}
No comments yet
Contribute on Hacker News ↗