Skip to content

Instantly share code, notes, and snippets.

@clembu
Created October 13, 2017 17:51
Show Gist options
  • Select an option

  • Save clembu/09d6c28bf56c6aa5ab34112099190798 to your computer and use it in GitHub Desktop.

Select an option

Save clembu/09d6c28bf56c6aa5ab34112099190798 to your computer and use it in GitHub Desktop.
Forks and suspends
#define _XOPEN_SOURCE 700
#define _POSIX_C_SOURCE 200809L
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
// This was a school exercise to help us understand signals.
// I'm putting it out here for future reference,
// though we have been warned:
// waiting for child processes is better done with `wait()`
// sigsuspend() was just to show us "hey this thing exists".
void pid(int i, pid_t pids[]) {
pids[i] = getpid();
}
void sigchld(int sig) {
printf("[%d]: SIGCHLD (%d)\n",getpid(),sig);
}
void done() {
printf("[%d] - DONE\n",getpid());
}
int main(int argc, char *argv[])
{
if(argc < 2) {
fprintf(stderr,"Wrong number of arguments. Provide a number of processes.");
exit(-1);
}
sigset_t msk,omsk;
sigemptyset(&msk); sigaddset(&msk,SIGCHLD); sigaddset(&msk,SIGINT);
int i = 0;
int N = atoi(argv[1]);
pid_t pids[N+1];
pid(i,pids);
for (i = 1; i <= N; ++i) {
int p = fork();
if(p == -1) {
perror("FORK ERROR");
} else if(p != 0) {
struct sigaction act;
act.sa_handler = &sigchld;
act.sa_flags = SA_NOCLDSTOP;
//i'm your father
if (sigaction(SIGCHLD,&act,NULL) < 0){
perror("sigaction");
exit(EXIT_FAILURE);
}
printf("[%d] I am a father! Mask: %d\n",getpid(),&msk);
if(sigprocmask(SIG_BLOCK,&msk,&omsk) < 0){
perror("block");
exit(EXIT_FAILURE);
}
printf("[%d] I am sleeping. Mask: %d (%d)\n",getpid(),&msk,&omsk);
sleep(1);
printf("[%d] I am awake! Mask: %d (%d)\n",getpid(),&msk,&omsk);
sigsuspend(&omsk);
printf("[%d] I haz signal!\n",getpid());
if(sigprocmask(SIG_UNBLOCK,&msk,NULL) < 0){
perror("unblock");
exit(EXIT_FAILURE);
}
printf("[%d] I just unblocked. Mask: %d (%d)\n",getpid(),&msk,&omsk);
break;
} else {
pid(i,pids);
}
}
i -= 1;
// i is important only at the end of the chain,
// where we want it to be `N`, not `N+1`
if (getpid() == pids[0]) {
//i'm the father
printf("[%d] I'm the father\n",getpid());
done();
exit(0);
} else if(i == N) {
//i'm the youngun
for (i = 0; i <= N; ++i) {
printf("PID %d -> %d\n",i,pids[i]);
}
done();
exit(0);
} else {
printf("[%d] I'm the middle man.\n",getpid());
//i'm the middleman
printf("%d > %d\n",getppid(),getpid());
done();
exit(0);
}
return -2;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment