Skip to content

Instantly share code, notes, and snippets.

@SarKerson
Created December 19, 2018 14:38
Show Gist options
  • Save SarKerson/441a46eebf8819eacd8efe72b73d390d to your computer and use it in GitHub Desktop.
Save SarKerson/441a46eebf8819eacd8efe72b73d390d to your computer and use it in GitHub Desktop.
I implement a sigprocmask program that described in CSAPP, but the parent-process only received SIGCHLD from its children once or twice, no mater how many times it fork()

the expected result would be:(the number of add is the same as del)

add job 12987
add job 12988
Wed Dec 19 22:20:59 CST 2018
del from 12987
Wed Dec 19 22:21:00 CST 2018
del from 12988
add job 12989
add job 12990
del from 12989
Wed Dec 19 22:21:01 CST 2018
add job 12991
Wed Dec 19 22:21:02 CST 2018
del from 12990
Wed Dec 19 22:21:03 CST 2018
del from 12991

but the result is:(Not all the SIGCHLD would be catched by the parent-process)

add job 12987
add job 12988
Wed Dec 19 22:20:59 CST 2018
del from 12987
now the list is: 12988
Wed Dec 19 22:21:00 CST 2018
del from 12988
now the list is: 
add job 12989
add job 12990
Wed Dec 19 22:21:01 CST 2018
add job 12991
Wed Dec 19 22:21:02 CST 2018
add job 12992
Wed Dec 19 22:21:03 CST 2018
add job 12993
Wed Dec 19 22:21:04 CST 2018
add job 12994
Wed Dec 19 22:21:05 CST 2018
add job 13091
Wed Dec 19 22:21:06 CST 2018
add job 13092
Wed Dec 19 22:21:07 CST 2018
Wed Dec 19 22:21:08 CST 2018 
#include "apue.h"
#include <sys/wait.h>
#include <sys/signal.h>
#include <errno.h>
void printJobs();
void addJob(int);
void delJob();
void handler(int sig)
{
sigset_t mask_all, pre_all;
sigfillset(&mask_all); // fill all bits of the mask
pid_t pid;
while ((pid = waitpid(-1, NULL, 0)) > 0) {
sigprocmask(SIG_BLOCK, &mask_all, &pre_all);
printf("del from %d\n", pid);
delJob(pid);
sigprocmask(SIG_UNBLOCK, &pre_all, NULL);
}
if (errno != ECHILD)
printf("waitpid error\n");
}
int main(int argc, char **argv)
{
pid_t pid;
sigset_t mask_all, mask_one, pre_one;
sigfillset(&mask_all);
sigemptyset(&mask_one);
sigaddset(&mask_one, SIGCHLD);
signal(SIGCHLD, handler);
for (int i = 0; i < 10; ++i) {
sigprocmask(SIG_BLOCK, &mask_one, &pre_one); // block SIGCHLD
if ((pid = fork()) == 0) {
sigprocmask(SIG_SETMASK, &pre_one, NULL);
sleep(1);
execve("/bin/date", argv, NULL);
}
sigprocmask(SIG_BLOCK, &mask_all, NULL); // block all sigals
addJob(pid);
sigprocmask(SIG_SETMASK, &pre_one, NULL); // unblock SIGCHLD
sleep(1);
}
exit(0);
}
typedef struct Node {
int val;
struct Node *next;
} Node, *pNode;
pNode phead = NULL, ptail = NULL;
void printJobs()
{
pNode pt = phead;
while (pt) {
printf("%d", pt->val);
pt = pt->next;
}
printf("\n");
}
void delJob(int pid)
{
if (ptail) {
pNode pt = phead, pre = NULL;
while (pt && pt->val != pid) {
pre = pt;
pt = pt->next;
}
if (!pt) {
printf("No job %d\n", pid);
return;
}
if (pt == phead) { // only have one node or empty
phead = phead->next ? phead->next : NULL;
free(pt);
ptail = phead ? ptail : NULL;
} else { // have more than one nodes
printf("del %d\n", pt->val);
free(pt);
pre->next = NULL;
ptail = pt == ptail ? pre : ptail;
}
printf("now the list is: ");
printJobs();
} else {
printf("No job %d\n", pid);
}
}
void addJob(int pid)
{
printf("add job %d\n", pid);
pNode pt = malloc(sizeof(Node));
pt->val = pid;
pt->next = NULL;
if (!phead) {
phead = ptail = pt;
} else {
ptail->next = pt;
ptail = pt;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment