https://access.redhat.com/solutions/629953
SOLUTION 已验证 - 已更新 2018年七月18日06:44 -
环境
- Red Hat Enterprise Linux
问题
- kill command does not kill the process when it sends SIGTERM or SIGHUP signal to the process because signal is blocked in parent and same mask is shared by child process.
决议
- At the time of spawning child process, it is inherited mask from parent and if it is not cleared then the same mask is set for the child also.
根源
- Signal (SIGTERM,SIGHUP) are blocked by the Parent process and same mask is shared to child without cleared so the child process is not killed by kill command.
- By default kill send the SIGTERM to the process
诊断步骤
Create a sig.c file with these contents:
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
void
do_stuff (void)
{
puts ("Doing stuff while waiting for signal....");
}
int
main (void)
{
sigset_t set;
/* Next line blocks signal SIGTERM(15) for this process */
sigaddset(&set,15);
/* Next line blocks signal for this process */
sigprocmask(SIG_BLOCK,&set,NULL);
/* Set an alarm to go off in a little while. */
/* Check the flag once in a while to see when to quit. */
while (1)
do_stuff ();
return EXIT_SUCCESS;
}
To compile, please execute the below command:
gcc sig.c -g -o sig
please run below to execute process
./sig
strace ./sig
rt_sigprocmask(SIG_BLOCK, [HUP INT QUIT USR1 USR2 PIPE ALRM TERM CHLD CONT STOP TTIN TTOU URG VTALRM PROF WINCH IO SYS], NULL, 8) = 0
Below is the system-tap script which is useful to ensure signal mask set by the process
#! /usr/bin/env stap
probe process("/lib*/libc.so.*").function("__sigprocmask")
{
printf("Glibc sigprocmask timestamp is %-25s, %s(%d) and parent pid is %d: call function %s thread id is %d and how is %d\n", ctime(gettimeofday_s()),execname(), pid(), ppid(),probefunc(),tid(),$how)
if($set)
printf("New mask for sigproc_mask is %x\n",$set->__val[0]);
else
printf("New mask for sigproc_mask is NULL");
if($oset)
printf("Old mask for sigproc_mask is %x\n",$oset->__val[0]);
else
printf("Old mask for sigproc_mask is NULL");
printf("\n\n")
}
probe process("/lib*/libpthread.so.0").function("pthread_sigmask")
{
printf("pthread_sigmask timestamp is %-25s, %s(%d) and parent pid is %d: call function %s thread id is %d and how is %d\n", ctime(gettimeofday_s()),execname(), pid(),ppid(), probefunc(),tid(),$how);
if($newmask)
printf("New mask for pthread_sigmask is %x\n",$newmask->__val[0]);
else
printf("New mask for pthread_sigmask is NULL");
if($oldmask)
printf("Old mask for pthread_sigmask is %x\n",$oldmask->__val[0]);
else
printf("Old mask for pthread_sigmask is NULL");
printf("\n\n")
}
probe kernel.function("sigprocmask")
{
printf("Kernel sigprocmask timestamp is %-25s, %s(%d) and parentpid is %d: call function %s thread id is %d how is %d\n", ctime(gettimeofday_s()),execname(), pid(), ppid(),probefunc(),tid(), $how);
if($set) {
printf("Sigset value is %x\n", $set->sig[0]);
printf("sigprocmask Sigset value is %s\n",sigset_mask_str($set->sig[0]));
} else
printf("Sigset value is NULL");
if($oldset) {
printf("Old Sigset value is %x\n", $oldset->sig[0]);
printf("sigprocmask Old Sigset value is %s\n",sigset_mask_str($oldset->sig[0]));
} else
printf("Old Sigset value is NULL");
printf("\n\n")
}
For RHEL-7 a sample system-tap script
probe kernel.function("sys_rt_sigprocmask")
{
if($1 == pid()) {
printf("%s(%d): call function %s thread id is %d parms %s\n",execname(), pid(), probefunc(),tid(), $$parms$$);
printf("Sigset value is %x\n", &@cast($nset, "sigset_t")->sig[0])
printf("\n\n")
}
}
To check which signals are blocked for specific process run below command
cat /proc/<pid>/status |grep ^Sig
SigQ: 1/62809
SigPnd: 0000000000000000
SigBlk: 0000000056727a01
SigIgn: 0000000000381000
SigCgt: 00000001c98044ff
From above output it is confirmed signals no (1,10,12,13,14,15 etc) are blocked for this process.