Created
October 13, 2017 17:51
-
-
Save clembu/09d6c28bf56c6aa5ab34112099190798 to your computer and use it in GitHub Desktop.
Forks and suspends
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
| #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