Skip to content

Instantly share code, notes, and snippets.

@fenrig
Created February 25, 2020 14:40
Show Gist options
  • Save fenrig/d505d47aa0b4f28ce0ea134ddd7e1650 to your computer and use it in GitHub Desktop.
Save fenrig/d505d47aa0b4f28ce0ea134ddd7e1650 to your computer and use it in GitHub Desktop.
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/wait.h>
#include <sys/prctl.h>
#include <unistd.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <errno.h>
#include <stdbool.h>
#include <poll.h>
#include <sys/signalfd.h>
#include <string.h>
static int sig_fd = -1;
static sigset_t mask;
static int syssig_enable(const int sigid, const bool enable){
if(enable) {
sigaddset(&mask, sigid);
} else {
sigdelset(&mask, sigid);
}
sig_fd = signalfd(sig_fd, &mask, SFD_CLOEXEC);
return 0;
}
static int syssig_read(void){
ssize_t res = 0;
struct signalfd_siginfo si;
res = read(sig_fd, &si, sizeof(si));
printf("res: %d | si.ssi_signo: %s\n", res, strsignal(si.ssi_signo));
return 0;
}
static void close_fds(void) {
struct rlimit limit;
int max_files = 1024;
int ret = getrlimit(RLIMIT_NOFILE, &limit);
if(ret == 0) {
max_files = limit.rlim_cur;
}
for(int i = 3; i < max_files; i++) {
close(i);
}
}
static void exec_child(char **argv){
int fd_null = -1;
sigset_t sig_set;
prctl(PR_SET_PDEATHSIG, SIGKILL);
fd_null = open("/dev/null", O_RDWR);
for(int i = 0; i < 3; i++) {
dup2(fd_null, i);
}
close_fds();
pthread_sigmask(SIG_SETMASK, NULL, &sig_set);
pthread_sigmask(SIG_UNBLOCK, &sig_set, NULL);
execvp(argv[0], argv);
exit(EXIT_FAILURE);
}
static void catch_sigchld(int signo){
int saved_errno = errno;
int status;
pid_t pid;
pid = waitpid((pid_t)(-1), &status, WNOHANG);
printf("pid: %d | errno: %d\n", pid, saved_errno);
errno = saved_errno;
}
static void catch_signal_empty(int signo){
printf("signo: %d\n", signo);
}
static int subproces(char **argv){
int err;
sigset_t ss, saved_ss;
if(argv == NULL){
return -1;
}
// block all signals
sigfillset(&ss);
//sigemptyset(&ss);
//sigaddset(&ss, SIGCHLD);
sigprocmask(SIG_SETMASK, &ss, &saved_ss);
pid_t pid = fork();
if( pid ){
// restore signals
sigprocmask(SIG_SETMASK, &saved_ss, NULL);
printf("launched: pid = %d\n", pid);
return 0;
}
close(sig_fd);
exec_child(argv);
// unreachable code
return -1;
}
static int poc_poll(void){
int err;
struct pollfd pollfd;
pollfd.fd = sig_fd;
pollfd.events = POLLIN;
err = poll(&pollfd, 1, -1);
printf("poll released: %d\n", err);
if(err){
syssig_read();
catch_sigchld(0);
}
return err;
}
int main(void){
int err;
char *cmd_sleep_2[] = { "sleep", "2", NULL};
char *runc_help[] = {"runc", "--help", NULL};
if (signal(SIGCHLD, catch_signal_empty) == SIG_ERR) {
printf("An error occurred while setting a signal handler.\n", stderr);
return EXIT_FAILURE;
}
sigemptyset(&mask);
sig_fd = signalfd(sig_fd, &mask, SFD_CLOEXEC);
syssig_enable(SIGCHLD, true);
/*
if (signal(SIGCHLD, catch_sigchld) == SIG_ERR) {
printf("An error occurred while setting a signal handler.\n", stderr);
return EXIT_FAILURE;
}
*/
err = subproces(cmd_sleep_2);
printf("sleep 2: err = %d\n", err);
err = subproces(runc_help);
printf("runc help: err = %d\n", err);
while(true){
poc_poll();
}
/*
while(1)
sleep(60);
*/
return 1;
}
poc_main: main.c
gcc -o poc_main main.c -lpthread
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment