CSAPP:撸一个Shell(二)

(二)接收不到子进程发送的SIGCHLD??

解决了前后进程的问题,很快又遇到了另外一个让我绞尽脑汁的问题,Shell创建的第二个子进程变成了zombie进程。不应该啊,因为我已经写了SIGCHLD的处理函数,如果子进程terminate,应该会发送一个SIGCHLD信号给Shell然后Shell进入处理函数进行回收。经过了printf的调试后我发现在第二次创建子进程后,子进程terminate之后就没有发送SIGCHLD信号给父进程了。

找了很多资料之后包括技术手册,发现并没有人出现这种情况,唯一相似的情况是在更改子进程组别的时候对应的父进程也被更改了,可是我查看了发现进程组别(PGID),和父进程(PPID)是不会相互影响的。

直到我重新修改了自己的代码突然发现没问题,然后再一步步倒回去才发现是出在sigprocmask的问题。

sigprocmask(SIG_SETMASK,&prev_one,NULL);

在每一次进程调用完毕后我都会调用sigprocmask(SIG_SETMASK,&prev_one,NULL),对信号阻塞字(进程中被阻塞的信号集)进行清0(不阻塞任何信号),然而我发现在第一次创建进程后prev_one的值从理论上应该是0改变了,也就是我的清0操作变成堵塞SIGCHLD,因此接收不到子进程发送过来的信号。

因此我需要去查看我的信号阻塞字:

sigprocmask(SIG_SETMASK,NULL,&prev_onet); 
   printf("4_case:%ld\n",prev_onet.__val[0]); 
   printf("4_case:%ld\n",prev_onet.__val[1]);

当sigprocmask第二个参数为NULL时不改变原状态,并且将原状态返回给prev_onet(如果他不是NULL),详见。查看pre_onet(信号阻塞集),如果直接用printf打印出来是没有意义的,因为他是一个结构体

typedef __sigset_t sigset_t;
#define _SIGSET_NWORDS   (1024 / (8 * sizeof(unsigned long int)))
typedef struct
{
    //此结构体占据unsigned long int * _SIGSET_NWORDS = 1024 bit 每bit对应一个信号 val[0]0-31位对应常用1-31信号
    unsigned long int __val[_SIGSET_NWORDS];
}__sigset_t;

最后发现信号是在第一次SIGCHLD中发生了改变(其实我早该想到第一次创建没问题,第二次有问题,那么问题一定出在这两次交接的程序部分)

void sigchld_handler(int sig) 
{
              ...
	     sigprocmask(SIG_BLOCK,&mask_all,&prev_one);
              ...
}

linux的机制是进入一个中断处理函数后会将该信号阻塞,也就是无法被相同信号的中断,因此我这时获取他的原状态prev_one就已经是阻塞SIGCHLD的状态了。。。。。把自己看傻了。。。。。。

总结:

1.这件事告诉我尽量不要一个改变状态的变量用在多个地方…..因为出了问题后你永远不知道他在哪里搞鬼….

2.能使用“常量”就不要使用变量,像sigprocmask(SIG_SETMASK,&prev_one,NULL),我完全可以专门使用一个用来清零的常量(像empty_one),而不是使用一个经常改变的量。

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇